Compare commits
	
		
			194 Commits
		
	
	
		
			0.2.3
			...
			356dc1848c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 356dc1848c | |||
| f551fdf87b | |||
| 6f3877700e | |||
| 2483faef01 | |||
| 82365a24ba | |||
| a29e33a3f9 | |||
| 273548411b | |||
| a8f481ff4a | |||
| 7fe0f19adf | |||
| b52cdf0f34 | |||
| 1c9c265ba8 | |||
| b5080d8c04 | |||
| bf107f9a18 | |||
| 8cd67cd68c | |||
| 5c7db72723 | |||
| 86433e841b | |||
| 61b2432d0b | |||
| ddb9d0e647 | |||
| a57c8da72a | |||
| c6a5d49942 | |||
| 27ccdbd980 | |||
| a5ef2551e8 | |||
| c632ad51d4 | |||
| 4f433c3840 | |||
| 455c1e7023 | |||
| 9ade299be7 | |||
| 09dcc8a9d3 | |||
| bd79831892 | |||
| c7967c6904 | |||
| a43676e9bf | |||
| fa7e41469b | |||
| c9ce81701f | |||
| c407c59c1a | |||
| 7e5706137e | |||
| 144c1d7e79 | |||
| 054266bfa0 | |||
| eaae058754 | |||
| 95a64732f3 | |||
| 57d59e91ac | |||
| e3d3d200d6 | |||
| 7da60e6f0a | |||
| 95e33109fe | |||
| 9e937f17b7 | |||
| 5dca2e5fed | |||
| f24fd5e880 | |||
| cfd96126df | |||
| 9099ebe4f3 | |||
| c666ceb51e | |||
| e5eb50a3cb | |||
| f0f23163e4 | |||
| faaadb0009 | |||
| fe32604a14 | |||
| 9b39d9baa5 | |||
| 7f2cdc5b1c | |||
| 4ffbbd5b89 | |||
| 898b24c8ee | |||
| ccbe60b747 | |||
| 22456946b8 | |||
| e4fcc7931e | |||
| e0af7421a1 | |||
| c2ed8b9bc5 | |||
| e27d2ae682 | |||
| b8fcaa48a5 | |||
| 6a18b15447 | |||
| b2397fcc2f | |||
| 7ed30c40be | |||
| 63000636a8 | |||
| 3d27295b14 | |||
| 1b587b049a | |||
| dc90258a28 | |||
| 23fde793db | |||
| 6640d70440 | |||
| 6e39154c75 | |||
| 164671a07c | |||
| 8aee72856c | |||
| 8118d4edc3 | |||
| 861a847088 | |||
| 666c527730 | |||
| e6e26b77f9 | |||
| 5a3eb57c0b | |||
| e1dbab3f4f | |||
| 3516a164da | |||
| e1304cc602 | |||
| 88f00c6046 | |||
| 09a6062992 | |||
| c92403f274 | |||
| 422c9bbb25 | |||
| e45d156e74 | |||
| 8e32362333 | |||
| 801d4bf16b | |||
| f7fd15b4bd | |||
| ac5271de6d | |||
| 1f2087f50f | |||
| 1c5b776efb | |||
| 368a00434b | |||
| 242af637f7 | |||
| 6d8aa26883 | |||
| bf2a412dec | |||
| 811e9991d0 | |||
| 5cbd6ec00b | |||
| b9c793ebb7 | |||
| 76c14a79ed | |||
| 877efe086b | |||
| 3b2ab6c8a0 | |||
| 7c0f30ff95 | |||
| 8719452dad | |||
| 24a3a48478 | |||
| ea026b351e | |||
| 109d3f28a2 | |||
| af5b9a2341 | |||
| 25a6758c40 | |||
| a685ab9e06 | |||
| 7b8f42ad59 | |||
| a691808068 | |||
| ecd648a9b2 | |||
| f891587ce3 | |||
| ffe7b5e109 | |||
| 602b1f3f98 | |||
| 17a14cedb6 | |||
| e31c5472af | |||
| 46ed616560 | |||
| 47f294a982 | |||
| 0fcf2c7b45 | |||
| fd2d30ee7f | |||
| e9b74140b5 | |||
| 27442fe7c7 | |||
| b748435f98 | |||
| d60baa0dce | |||
| 48507962f8 | |||
| 7d4f3e9541 | |||
| 3b9ef0048e | |||
| 523e019aa0 | |||
| d0d053152d | |||
| 8231d20e3b | |||
| f35dd0b15d | |||
| d778bd2719 | |||
| 0c42c6554c | |||
| fbc7b58780 | |||
| 840193d5a8 | |||
| 4869039503 | |||
| d0ded956cb | |||
| 47a73a4298 | |||
| a082b879ca | |||
| a51efa641d | |||
| f553779797 | |||
| dee8e4fe74 | |||
| 7760ee5725 | |||
| 1055d5c2e1 | |||
| c094a3efae | |||
| 2a97438417 | |||
| a69c223a33 | |||
| 1baa8cee60 | |||
| 3d17bb7703 | |||
| d7a0706e0c | |||
| dfcc516389 | |||
| 1857473ccc | |||
| 90bfee23b4 | |||
| f634ad552e | |||
| 29fa35dffe | |||
| c5f371e0d5 | |||
| f319e89473 | |||
| d5ad5ded88 | |||
| dbbd2b54c4 | |||
| 1a3126dfc5 | |||
| ba881aefa8 | |||
| 3fe8e1503c | |||
| 651482a1b9 | |||
| 8c3cd1fae7 | |||
| ee49bde961 | |||
| 2b08c1d71e | |||
| ead3f69a69 | |||
| 029b46d7de | |||
| 9da95f4dfb | |||
| 8e56ff6a8e | |||
| 21fcfaaa7f | |||
| 119f4e9d04 | |||
| 5cd91d8341 | |||
| e0844a7f92 | |||
| 6f95d0a055 | |||
| 1090e502c2 | |||
| 1defe29406 | |||
| 126637306d | |||
| 2457107c63 | |||
| 411e44a681 | |||
| 91b054fdca | |||
| e8c491a478 | |||
| aab3d62365 | |||
| 0927288bb5 | |||
| 0019f868ad | |||
| d05dec3605 | |||
| 30dbce3f4b | |||
| 56db9f42ad | |||
| 85f5717624 | |||
| 0c71e4934e | 
| @@ -1,26 +0,0 @@ | |||||||
| { |  | ||||||
|   "WorkspaceSettings": { |  | ||||||
|     "DefaultProject": "bot", |  | ||||||
|     "Projects": { |  | ||||||
|       "bot": "src/bot/bot.json", |  | ||||||
|       "bot-core": "src/bot_core/bot-core.json", |  | ||||||
|       "bot-data": "src/bot_data/bot-data.json", |  | ||||||
|       "admin": "src/modules/admin/admin.json", |  | ||||||
|       "auto-role": "src/modules/auto_role/auto-role.json", |  | ||||||
|       "base": "src/modules/base/base.json", |  | ||||||
|       "boot-log": "src/modules/boot_log/boot-log.json", |  | ||||||
|       "database": "src/modules/database/database.json", |  | ||||||
|       "moderator": "src/modules/moderator/moderator.json", |  | ||||||
|       "permission": "src/modules/permission/permission.json" |  | ||||||
|     }, |  | ||||||
|     "Scripts": { |  | ||||||
|       "prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;", |  | ||||||
|       "stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;", |  | ||||||
|       "dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;", |  | ||||||
|  |  | ||||||
|       "build-docker": "cpl b; docker-compose down; docker build -t kdb .", |  | ||||||
|       "compose": "docker-compose up -d", |  | ||||||
|       "docker": "cpl build-docker; cpl compose;" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,64 +0,0 @@ | |||||||
| version: "3.9" |  | ||||||
|  |  | ||||||
| volumes: |  | ||||||
|   kdb_prod_1: |  | ||||||
|   kdb_staging_1: |  | ||||||
|   kdb_db_1: |  | ||||||
|   kdb_db_2: |  | ||||||
|  |  | ||||||
| services: |  | ||||||
|   kdb_prod_1: |  | ||||||
|     image: kdb/kdb:0.2.1 |  | ||||||
|     container_name: kdb_prod_1 |  | ||||||
|     depends_on: |  | ||||||
|       - kdb_db_1 |  | ||||||
|     volumes: |  | ||||||
|       - kdb_prod_1:/app |  | ||||||
|     environment: |  | ||||||
|       KDB_ENVIRONMENT: "production" |  | ||||||
|       KDB_TOKEN: "" |  | ||||||
|       KDB_PREFIX: "!k " |  | ||||||
|     restart: 'no' |  | ||||||
|  |  | ||||||
|   kdb_staging_1: |  | ||||||
|     image: kdb/kdb:0.2.1 |  | ||||||
|     container_name: kdb_staging_1 |  | ||||||
|     depends_on: |  | ||||||
|       - kdb_db_1 |  | ||||||
|     volumes: |  | ||||||
|       - kdb_staging_1:/app |  | ||||||
|     environment: |  | ||||||
|       KDB_ENVIRONMENT: "staging" |  | ||||||
|       KDB_TOKEN: "" |  | ||||||
|       KDB_PREFIX: "!kt " |  | ||||||
|     restart: 'no' |  | ||||||
|  |  | ||||||
|   kdb_db_1: |  | ||||||
|     image: mysql:latest |  | ||||||
|     container_name: kdb_db_1 |  | ||||||
|     command: mysqld --default-authentication-plugin=mysql_native_password |  | ||||||
|     restart: unless-stopped |  | ||||||
|     environment: |  | ||||||
|       MYSQL_ROOT_PASSWORD: "kd_kdb" |  | ||||||
|       MYSQL_USER: "kd_kdb" |  | ||||||
|       MYSQL_PASSWORD: "kd_kdb" |  | ||||||
|       MYSQL_DATABASE: "kd_kdb" |  | ||||||
|     ports: |  | ||||||
|       - "3307:3306" |  | ||||||
|     volumes: |  | ||||||
|       - kdb_db_1:/var/lib/mysql |  | ||||||
|  |  | ||||||
|   kdb_db_2: |  | ||||||
|     image: mysql:latest |  | ||||||
|     container_name: kdb_db_2 |  | ||||||
|     command: mysqld --default-authentication-plugin=mysql_native_password |  | ||||||
|     restart: unless-stopped |  | ||||||
|     environment: |  | ||||||
|       MYSQL_ROOT_PASSWORD: "kd_kdb" |  | ||||||
|       MYSQL_USER: "kd_kdb" |  | ||||||
|       MYSQL_PASSWORD: "kd_kdb" |  | ||||||
|       MYSQL_DATABASE: "kd_kdb" |  | ||||||
|     ports: |  | ||||||
|       - "3308:3306" |  | ||||||
|     volumes: |  | ||||||
|       - kdb_db_2:/var/lib/mysql |  | ||||||
							
								
								
									
										18
									
								
								dockerfile
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								dockerfile
									
									
									
									
									
								
							| @@ -1,18 +0,0 @@ | |||||||
| # syntax=docker/dockerfile:1 |  | ||||||
| FROM python:3.10.7-bullseye |  | ||||||
|  |  | ||||||
| WORKDIR /app |  | ||||||
| COPY ./dist/bot/build/ . |  | ||||||
|  |  | ||||||
| RUN pip install cpl-core --extra-index-url https://pip.sh-edraft.de |  | ||||||
| RUN pip install cpl-discord --extra-index-url https://pip.sh-edraft.de |  | ||||||
| RUN pip install cpl-query --extra-index-url https://pip.sh-edraft.de |  | ||||||
| RUN pip install cpl-translation --extra-index-url https://pip.sh-edraft.de |  | ||||||
| RUN apt-get update -y |  | ||||||
| RUN apt-get install nano -y |  | ||||||
|  |  | ||||||
| ENV KDB_TOKEN="" |  | ||||||
| ENV KDB_PREFIX="!kdb " |  | ||||||
| ENV KDB_ENVIRONMENT="production" |  | ||||||
|  |  | ||||||
| CMD [ "bash", "/app/bot/bot"] |  | ||||||
							
								
								
									
										44
									
								
								kdb-bot/cpl-workspace.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								kdb-bot/cpl-workspace.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | { | ||||||
|  |   "WorkspaceSettings": { | ||||||
|  |     "DefaultProject": "bot", | ||||||
|  |     "Projects": { | ||||||
|  |       "bot": "src/bot/bot.json", | ||||||
|  |       "bot-api": "src/bot_api/bot-api.json", | ||||||
|  |       "bot-core": "src/bot_core/bot-core.json", | ||||||
|  |       "bot-data": "src/bot_data/bot-data.json", | ||||||
|  |       "auto-role": "src/modules/auto_role/auto-role.json", | ||||||
|  |       "base": "src/modules/base/base.json", | ||||||
|  |       "boot-log": "src/modules/boot_log/boot-log.json", | ||||||
|  |       "database": "src/modules/database/database.json", | ||||||
|  |       "level": "src/modules/level/level.json", | ||||||
|  |       "permission": "src/modules/permission/permission.json", | ||||||
|  |       "stats": "src/modules/stats/stats.json", | ||||||
|  |       "get-version": "tools/get_version/get-version.json", | ||||||
|  |       "post-build": "tools/post_build/post-build.json", | ||||||
|  |       "set-version": "tools/set_version/set-version.json" | ||||||
|  |     }, | ||||||
|  |     "Scripts": { | ||||||
|  |       "sv": "cpl set-version", | ||||||
|  |       "set-version": "cpl run set-version $ARGS; echo '';", | ||||||
|  |  | ||||||
|  |       "gv": "cpl get-version", | ||||||
|  |       "get-version": "export VERSION=$(cpl run get-version); echo $VERSION;", | ||||||
|  |  | ||||||
|  |       "pre-build": "cpl set-version $ARGS", | ||||||
|  |       "post-build": "cpl run post-build", | ||||||
|  |  | ||||||
|  |       "pre-prod": "cpl build", | ||||||
|  |       "prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;", | ||||||
|  |  | ||||||
|  |       "pre-stage": "cpl build", | ||||||
|  |       "stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;", | ||||||
|  |  | ||||||
|  |       "pre-dev": "cpl build", | ||||||
|  |       "dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;", | ||||||
|  |  | ||||||
|  |       "docker-build": "cpl b; docker-compose down; docker build -t kdb-bot/kdb-bot:$(cpl gv) .", | ||||||
|  |       "docker-compose": "docker-compose up -d", | ||||||
|  |       "docker": "cpl docker-build; cpl docker-compose;" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								kdb-bot/docker-compose.dev.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								kdb-bot/docker-compose.dev.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | version: "3.9" | ||||||
|  |  | ||||||
|  | volumes: | ||||||
|  |   kdb_bot_dev_1: | ||||||
|  |   kdb_web_dev_1: | ||||||
|  |   kdb_db_dev_1: | ||||||
|  |  | ||||||
|  | services: | ||||||
|  |   kdb_bot_dev_1: | ||||||
|  |     image: kdb-bot/kdb-bot:0.3 | ||||||
|  |     container_name: kdb_bot_dev_1 | ||||||
|  |     depends_on: | ||||||
|  |       - kdb_db_dev_1 | ||||||
|  |     volumes: | ||||||
|  |       - kdb_bot_dev_1:/app | ||||||
|  |     environment: | ||||||
|  |       KDB_ENVIRONMENT: "dev" | ||||||
|  |       KDB_TOKEN: "OTk4MTU5NjczODkzMDYwNzM4.GN3QyA.yvWO6L7Eu36gXQ7ARDs0Jg2J1VqIDnHLou5lT4" | ||||||
|  |       KDB_PREFIX: "!kd " | ||||||
|  |     restart: 'no' | ||||||
|  |     ports: | ||||||
|  |       - '8044:80' | ||||||
|  |     command: bash /app/bot/bot -dev | ||||||
|  |  | ||||||
|  |   kdb_web_dev_1: | ||||||
|  |     image: kdb-web/kdb-web:0.3 | ||||||
|  |     container_name: kdb_web_dev_1 | ||||||
|  |     depends_on: | ||||||
|  |       - kdb_bot_dev_1 | ||||||
|  |     volumes: | ||||||
|  |       - kdb_web_dev_1:/app | ||||||
|  |     restart: 'no' | ||||||
|  |     ports: | ||||||
|  |       - '8043:80' | ||||||
|  |  | ||||||
|  |   kdb_db_dev_1: | ||||||
|  |     image: mysql:latest | ||||||
|  |     container_name: kdb_db_dev_1 | ||||||
|  |     command: mysqld --default-authentication-plugin=mysql_native_password | ||||||
|  |     restart: unless-stopped | ||||||
|  |     environment: | ||||||
|  |       MYSQL_ROOT_PASSWORD: "kd_kdb" | ||||||
|  |       MYSQL_USER: "kd_kdb" | ||||||
|  |       MYSQL_PASSWORD: "!w5D_&steCejfjq~b{0_DP@e:§X2?JUz" | ||||||
|  |       MYSQL_DATABASE: "kd_kdb" | ||||||
|  |     ports: | ||||||
|  |       - "3308:3306" | ||||||
|  |     volumes: | ||||||
|  |       - kdb_db_dev_1:/var/lib/mysql | ||||||
							
								
								
									
										49
									
								
								kdb-bot/docker-compose.staging.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								kdb-bot/docker-compose.staging.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | version: "3.9" | ||||||
|  |  | ||||||
|  | volumes: | ||||||
|  |   kdb_bot_staging_1: | ||||||
|  |   kdb_web_staging_1: | ||||||
|  |   kdb_db_staging_1: | ||||||
|  |  | ||||||
|  | services: | ||||||
|  |   kdb_bot_staging_1: | ||||||
|  |     image: kdb-bot/kdb-bot:0.3 | ||||||
|  |     container_name: kdb_bot_staging_1 | ||||||
|  |     depends_on: | ||||||
|  |       - kdb_db_staging_1 | ||||||
|  |     volumes: | ||||||
|  |       - kdb_bot_staging_1:/app | ||||||
|  |     environment: | ||||||
|  |       KDB_ENVIRONMENT: "staging" | ||||||
|  |       KDB_TOKEN: "OTk4MTU5ODAyMzkzOTY0NTk0.G4rLkF.uBQ9pW8X1Lm5agHqvBfzf7qEf8Ton-3a1oJPmY" | ||||||
|  |       KDB_PREFIX: "!kt " | ||||||
|  |     restart: 'no' | ||||||
|  |     ports: | ||||||
|  |       - '8044:80' | ||||||
|  |     command: bash /app/bot/bot -stage | ||||||
|  |  | ||||||
|  |   kdb_web_staging_1: | ||||||
|  |     image: kdb-web/kdb-web:0.3 | ||||||
|  |     container_name: kdb_web_staging_1 | ||||||
|  |     depends_on: | ||||||
|  |       - kdb_bot_staging_1 | ||||||
|  |     volumes: | ||||||
|  |       - kdb_web_staging_1:/app | ||||||
|  |     restart: 'no' | ||||||
|  |     ports: | ||||||
|  |       - '8043:80' | ||||||
|  |  | ||||||
|  |   kdb_db_staging_1: | ||||||
|  |     image: mysql:latest | ||||||
|  |     container_name: kdb_db_staging_1 | ||||||
|  |     command: mysqld --default-authentication-plugin=mysql_native_password | ||||||
|  |     restart: unless-stopped | ||||||
|  |     environment: | ||||||
|  |       MYSQL_ROOT_PASSWORD: "kd_kdb" | ||||||
|  |       MYSQL_USER: "kd_kdb" | ||||||
|  |       MYSQL_PASSWORD: "3&YwVMCwüb=LUt7B§ÖsY?Kr~XRtD#&&f" | ||||||
|  |       MYSQL_DATABASE: "kd_kdb" | ||||||
|  |     ports: | ||||||
|  |       - "3308:3306" | ||||||
|  |     volumes: | ||||||
|  |       - kdb_db_staging_1:/var/lib/mysql | ||||||
							
								
								
									
										48
									
								
								kdb-bot/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								kdb-bot/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | version: "3.9" | ||||||
|  |  | ||||||
|  | volumes: | ||||||
|  |   kdb_bot_prod_1: | ||||||
|  |   kdb_web_prod_1: | ||||||
|  |   kdb_db_prod_1: | ||||||
|  |  | ||||||
|  | services: | ||||||
|  |   kdb_bot_prod_1: | ||||||
|  |     image: kdb-bot/kdb-bot:0.3 | ||||||
|  |     container_name: kdb_bot_prod_1 | ||||||
|  |     depends_on: | ||||||
|  |       - kdb_db_prod_1 | ||||||
|  |     volumes: | ||||||
|  |       - kdb_bot_prod_1:/app | ||||||
|  |     environment: | ||||||
|  |       KDB_ENVIRONMENT: "production" | ||||||
|  |       KDB_TOKEN: "" | ||||||
|  |       KDB_PREFIX: "!k " | ||||||
|  |     restart: 'no' | ||||||
|  |     ports: | ||||||
|  |       - '8041:80' | ||||||
|  |  | ||||||
|  |   kdb_web_prod_1: | ||||||
|  |     image: kdb-web/kdb-web:0.3 | ||||||
|  |     container_name: kdb_web_prod_1 | ||||||
|  |     depends_on: | ||||||
|  |       - kdb_bot_prod_1 | ||||||
|  |     volumes: | ||||||
|  |       - kdb_web_prod_1:/app | ||||||
|  |     restart: 'no' | ||||||
|  |     ports: | ||||||
|  |       - '8042:80' | ||||||
|  |  | ||||||
|  |   kdb_db_prod_1: | ||||||
|  |     image: mysql:latest | ||||||
|  |     container_name: kdb_db_prod_1 | ||||||
|  |     command: mysqld --default-authentication-plugin=mysql_native_password | ||||||
|  |     restart: unless-stopped | ||||||
|  |     environment: | ||||||
|  |       MYSQL_ROOT_PASSWORD: "kd_kdb" | ||||||
|  |       MYSQL_USER: "kd_kdb" | ||||||
|  |       MYSQL_PASSWORD: "+=gj}(ÄEbRG6_S&ö}ü>zaNT=rE{_~m<y" | ||||||
|  |       MYSQL_DATABASE: "kd_kdb" | ||||||
|  |     ports: | ||||||
|  |       - "3307:3306" | ||||||
|  |     volumes: | ||||||
|  |       - kdb_db_prod_1:/var/lib/mysql | ||||||
							
								
								
									
										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/ . | ||||||
|  |  | ||||||
|  | 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"] | ||||||
| @@ -15,7 +15,7 @@ __title__ = 'bot' | |||||||
| __author__ = 'Sven Heidemann' | __author__ = 'Sven Heidemann' | ||||||
| __license__ = 'MIT' | __license__ = 'MIT' | ||||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
| __version__ = '0.2.3' | __version__ = '0.3.dev25' | ||||||
| 
 | 
 | ||||||
| from collections import namedtuple | from collections import namedtuple | ||||||
| 
 | 
 | ||||||
| @@ -23,4 +23,4 @@ from collections import namedtuple | |||||||
| # imports:  | # imports:  | ||||||
| 
 | 
 | ||||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
| version_info = VersionInfo(major='0', minor='2', micro='3') | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
| @@ -7,6 +7,10 @@ from cpl_discord.configuration import DiscordBotSettings | |||||||
| from cpl_discord.service import DiscordBotServiceABC, DiscordBotService | from cpl_discord.service import DiscordBotServiceABC, DiscordBotService | ||||||
| from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings | from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings | ||||||
| 
 | 
 | ||||||
|  | from bot_api.api_thread import ApiThread | ||||||
|  | from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum | ||||||
|  | from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class Application(DiscordBotApplicationABC): | class Application(DiscordBotApplicationABC): | ||||||
| 
 | 
 | ||||||
| @@ -14,6 +18,7 @@ class Application(DiscordBotApplicationABC): | |||||||
|         DiscordBotApplicationABC.__init__(self, config, services) |         DiscordBotApplicationABC.__init__(self, config, services) | ||||||
| 
 | 
 | ||||||
|         self._services = services |         self._services = services | ||||||
|  |         self._config = config | ||||||
| 
 | 
 | ||||||
|         # cpl-core |         # cpl-core | ||||||
|         self._logger: LoggerABC = services.get_service(LoggerABC) |         self._logger: LoggerABC = services.get_service(LoggerABC) | ||||||
| @@ -24,6 +29,12 @@ class Application(DiscordBotApplicationABC): | |||||||
|         self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC) |         self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC) | ||||||
|         self._t: TranslatePipe = services.get_service(TranslatePipe) |         self._t: TranslatePipe = services.get_service(TranslatePipe) | ||||||
| 
 | 
 | ||||||
|  |         self._feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings) | ||||||
|  | 
 | ||||||
|  |         # api | ||||||
|  |         if self._feature_flags.get_flag(FeatureFlagsEnum.api_module): | ||||||
|  |             self._api: ApiThread = services.get_service(ApiThread) | ||||||
|  | 
 | ||||||
|         self._is_stopping = False |         self._is_stopping = False | ||||||
| 
 | 
 | ||||||
|     async def configure(self): |     async def configure(self): | ||||||
| @@ -32,6 +43,12 @@ 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': | ||||||
|  |                 self._api.start() | ||||||
|  |                 self._api.join() | ||||||
|  |                 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() | ||||||
| @@ -53,4 +70,4 @@ class Application(DiscordBotApplicationABC): | |||||||
|         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  # | ||||||
| @@ -14,9 +14,6 @@ elif [[ $1 == "-stage" ]]; then | |||||||
| elif [[ $1 == "-prod" ]]; then | elif [[ $1 == "-prod" ]]; then | ||||||
|     export KDB_ENVIRONMENT=production |     export KDB_ENVIRONMENT=production | ||||||
|     export KDB_NAME=KDB |     export KDB_NAME=KDB | ||||||
| else |  | ||||||
|     export KDB_ENVIRONMENT=production |  | ||||||
|     export KDB_NAME=KDB-prod |  | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| export PYTHONPATH=./:$PYTHONPATH | export PYTHONPATH=./:$PYTHONPATH | ||||||
| @@ -3,8 +3,8 @@ | |||||||
|     "Name": "bot", |     "Name": "bot", | ||||||
|     "Version": { |     "Version": { | ||||||
|       "Major": "0", |       "Major": "0", | ||||||
|       "Minor": "2", |       "Minor": "3", | ||||||
|       "Micro": "3" |       "Micro": "dev25" | ||||||
|     }, |     }, | ||||||
|     "Author": "Sven Heidemann", |     "Author": "Sven Heidemann", | ||||||
|     "AuthorEmail": "sven.heidemann@sh-edraft.de", |     "AuthorEmail": "sven.heidemann@sh-edraft.de", | ||||||
| @@ -16,18 +16,24 @@ | |||||||
|     "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.post6", |       "cpl-core==2022.10.0.post7", | ||||||
|       "cpl-translation==2022.10.0", |       "cpl-translation==2022.10.0.post2", | ||||||
|       "cpl-query==2022.10.0", |       "cpl-query==2022.10.0.post2", | ||||||
|       "cpl-discord==2022.10.0.post5" |       "cpl-discord==2022.10.0.post6", | ||||||
|  |       "Flask==2.2.2", | ||||||
|  |       "Flask-Classful==0.14.2", | ||||||
|  |       "Flask-Cors==3.0.10", | ||||||
|  |       "PyJWT==2.6.0", | ||||||
|  |       "waitress==2.1.2", | ||||||
|  |       "Flask-SocketIO==5.3.1", | ||||||
|  |       "eventlet==0.33.1", | ||||||
|  |       "requests-oauthlib==1.3.1" | ||||||
|     ], |     ], | ||||||
|     "DevDependencies": [ |     "DevDependencies": [ | ||||||
|       "cpl-cli==2022.10.0" |       "cpl-cli==2022.10.0" | ||||||
|     ], |     ], | ||||||
|     "PythonVersion": ">=3.10.4", |     "PythonVersion": ">=3.10.4", | ||||||
|     "PythonPath": { |     "PythonPath": {}, | ||||||
|       "linux": "" |  | ||||||
|     }, |  | ||||||
|     "Classifiers": [] |     "Classifiers": [] | ||||||
|   }, |   }, | ||||||
|   "BuildSettings": { |   "BuildSettings": { | ||||||
| @@ -45,6 +51,7 @@ | |||||||
|     ], |     ], | ||||||
|     "PackageData": {}, |     "PackageData": {}, | ||||||
|     "ProjectReferences": [ |     "ProjectReferences": [ | ||||||
|  |       "../bot_api/bot-api.json", | ||||||
|       "../bot_core/bot-core.json", |       "../bot_core/bot-core.json", | ||||||
|       "../bot_data/bot-data.json", |       "../bot_data/bot-data.json", | ||||||
|       "../modules/base/base.json", |       "../modules/base/base.json", | ||||||
| @@ -53,6 +60,7 @@ | |||||||
|       "../modules/base/base.json", |       "../modules/base/base.json", | ||||||
|       "../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/moderator/moderator.json", |       "../modules/moderator/moderator.json", | ||||||
|       "../modules/permission/permission.json" |       "../modules/permission/permission.json" | ||||||
|     ] |     ] | ||||||
| @@ -33,17 +33,17 @@ | |||||||
|   }, |   }, | ||||||
|   "DatabaseSettings": { |   "DatabaseSettings": { | ||||||
|     "Host": "localhost", |     "Host": "localhost", | ||||||
|     "User": "kd_kdb", |     "User": "root", | ||||||
|     "Password": "VGpZcihrb0N2T2MyZUlURQ==", |     "Password": "MTAwNjE5OTdOaWNrLko=", | ||||||
|     "Database": "keksdose_bot_dev", |     "Database": "kd_kdb", | ||||||
|     "Charset": "utf8mb4", |     "Charset": "utf8mb4", | ||||||
|     "UseUnicode": "true", |     "UseUnicode": "true", | ||||||
|     "Buffered": "true", |     "Buffered": "true", | ||||||
|     "AuthPlugin": "mysql_native_password" |     "AuthPlugin": "mysql_native_password" | ||||||
|   }, |   }, | ||||||
|   "DiscordBot": { |   "DiscordBot": { | ||||||
|     "Token": "OTk4MTYwNDI3Njg5MTgxMjM3.GI7h67.BqD6Lu1Tz0MuG8iktYrcLnHi1pNozyMiWFGTKI", |     "Token": "MTAyOTgxMjE0Mjk4NTE5MTYxNA.G4ArAJ.sZh6pE-mwO2qDAr1mfHEoo7EwbJb-TZT8h6nGg", | ||||||
|     "Prefix": "!ke " |     "Prefix": "!kn " | ||||||
|   }, |   }, | ||||||
|   "Bot": { |   "Bot": { | ||||||
|     "910199451145076828": { |     "910199451145076828": { | ||||||
| @@ -6,44 +6,61 @@ | |||||||
|     "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" |     "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" | ||||||
|   }, |   }, | ||||||
|   "LoggingSettings": { |   "LoggingSettings": { | ||||||
|     "Path": "logs/", |     "Path": "logs/$date_now/", | ||||||
|     "Filename": "bot.log", |     "Filename": "bot.log", | ||||||
|     "ConsoleLogLevel": "DEBUG", |     "ConsoleLogLevel": "TRACE", | ||||||
|     "FileLogLevel": "DEBUG" |     "FileLogLevel": "TRACE" | ||||||
|   }, |   }, | ||||||
|   "BotLoggingSettings": { |   "BotLoggingSettings": { | ||||||
|  |     "Api": { | ||||||
|  |       "Path": "logs/$date_now/", | ||||||
|  |       "Filename": "api.log", | ||||||
|  |       "ConsoleLogLevel": "TRACE", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     }, | ||||||
|     "Command": { |     "Command": { | ||||||
|       "Path": "logs/", |       "Path": "logs/$date_now/", | ||||||
|       "Filename": "commands.log", |       "Filename": "commands.log", | ||||||
|       "ConsoleLogLevel": "DEBUG", |       "ConsoleLogLevel": "TRACE", | ||||||
|       "FileLogLevel": "DEBUG" |       "FileLogLevel": "TRACE" | ||||||
|     }, |     }, | ||||||
|     "Database": { |     "Database": { | ||||||
|       "Path": "logs/", |       "Path": "logs/$date_now/", | ||||||
|       "Filename": "database.log", |       "Filename": "database.log", | ||||||
|       "ConsoleLogLevel": "DEBUG", |       "ConsoleLogLevel": "DEBUG", | ||||||
|       "FileLogLevel": "DEBUG" |       "FileLogLevel": "TRACE" | ||||||
|     }, |     }, | ||||||
|     "Message": { |     "Message": { | ||||||
|       "Path": "logs/", |       "Path": "logs/$date_now/", | ||||||
|       "Filename": "message.log", |       "Filename": "message.log", | ||||||
|       "ConsoleLogLevel": "DEBUG", |       "ConsoleLogLevel": "TRACE", | ||||||
|       "FileLogLevel": "DEBUG" |       "FileLogLevel": "TRACE" | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|  |   "DiscordBot": { | ||||||
|  |     "Token": "OTk4MTU5NjczODkzMDYwNzM4.GN3QyA.yvWO6L7Eu36gXQ7ARDs0Jg2J1VqIDnHLou5lT4", | ||||||
|  |     "Prefix": "!kd " | ||||||
|  |   }, | ||||||
|   "Translation": { |   "Translation": { | ||||||
|     "DefaultLanguage": "de", |     "DefaultLanguage": "de", | ||||||
|     "Languages": [ |     "Languages": [ | ||||||
|       "de" |       "de" | ||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "DiscordBot": { |   "DatabaseSettings": { | ||||||
|     "Token": "OTk4MTU5NjczODkzMDYwNzM4.GN3QyA.yvWO6L7Eu36gXQ7ARDs0Jg2J1VqIDnHLou5lT4", |     "Host": "kdb_db_dev_1", | ||||||
|     "Prefix": "!kd " |     "User": "kd_kdb", | ||||||
|  |     "Password": "IXc1RF8mc3RlQ2VqZmpxfmJ7MF9EUEBlOsKnWDI/SlV6", | ||||||
|  |     "Database": "kd_kdb", | ||||||
|  |     "Port": "3306", | ||||||
|  |     "Charset": "utf8mb4", | ||||||
|  |     "UseUnicode": "true", | ||||||
|  |     "Buffered": "true", | ||||||
|  |     "AuthPlugin": "mysql_native_password" | ||||||
|   }, |   }, | ||||||
|   "Bot": { |   "Bot": { | ||||||
|     "910199451145076828": { |     "910199451145076828": { | ||||||
|       "MessageDeleteTimer": 6 |       "MessageDeleteTimer": 4 | ||||||
|     }, |     }, | ||||||
|     "Technicians": [ |     "Technicians": [ | ||||||
|       240160344557879316, |       240160344557879316, | ||||||
| @@ -1,10 +1,42 @@ | |||||||
| { | { | ||||||
|  |   "TimeFormatSettings": { | ||||||
|  |     "DateFormat": "%Y-%m-%d", | ||||||
|  |     "TimeFormat": "%H:%M:%S", | ||||||
|  |     "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", | ||||||
|  |     "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" | ||||||
|  |   }, | ||||||
|   "LoggingSettings": { |   "LoggingSettings": { | ||||||
|     "Path": "logs/", |     "Path": "logs/", | ||||||
|     "Filename": "log_dev.log", |     "Filename": "bot.log", | ||||||
|     "ConsoleLogLevel": "DEBUG", |     "ConsoleLogLevel": "DEBUG", | ||||||
|     "FileLogLevel": "TRACE" |     "FileLogLevel": "TRACE" | ||||||
|   }, |   }, | ||||||
|  |   "BotLoggingSettings": { | ||||||
|  |     "Api": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "api.log", | ||||||
|  |       "ConsoleLogLevel": "TRACE", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     }, | ||||||
|  |     "Command": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "commands.log", | ||||||
|  |       "ConsoleLogLevel": "DEBUG", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     }, | ||||||
|  |     "Database": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "database.log", | ||||||
|  |       "ConsoleLogLevel": "DEBUG", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     }, | ||||||
|  |     "Message": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "message.log", | ||||||
|  |       "ConsoleLogLevel": "DEBUG", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   "DatabaseSettings": { |   "DatabaseSettings": { | ||||||
|     "Host": "localhost", |     "Host": "localhost", | ||||||
|     "User": "kd_kdb", |     "User": "kd_kdb", | ||||||
| @@ -26,7 +58,8 @@ | |||||||
|     "Technicians": [ |     "Technicians": [ | ||||||
|       240160344557879316 |       240160344557879316 | ||||||
|     ], |     ], | ||||||
|     "DeployFilesPath": "../../deploy" |     "WaitForRestart": 4, | ||||||
|  |     "WaitForShutdown": 4 | ||||||
|   }, |   }, | ||||||
|   "Base": { |   "Base": { | ||||||
|     "910199451145076828": { |     "910199451145076828": { | ||||||
| @@ -43,7 +76,12 @@ | |||||||
|   }, |   }, | ||||||
|   "BootLog": { |   "BootLog": { | ||||||
|     "910199451145076828": { |     "910199451145076828": { | ||||||
|       "LoginMessageChannelId": "910199452915093588" |       "LoginMessageChannelId": 910199452915093588 | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "Level": { | ||||||
|  |     "910199451145076828": { | ||||||
|  |       "ChangedLevelNotificationChannelId": 910199452667637892 | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   "Permission": { |   "Permission": { | ||||||
							
								
								
									
										97
									
								
								kdb-bot/src/bot/config/appsettings.edrafts-pc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								kdb-bot/src/bot/config/appsettings.edrafts-pc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | { | ||||||
|  |   "TimeFormatSettings": { | ||||||
|  |     "DateFormat": "%Y-%m-%d", | ||||||
|  |     "TimeFormat": "%H:%M:%S", | ||||||
|  |     "DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f", | ||||||
|  |     "DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S" | ||||||
|  |   }, | ||||||
|  |   "LoggingSettings": { | ||||||
|  |     "Path": "logs/", | ||||||
|  |     "Filename": "bot.log", | ||||||
|  |     "ConsoleLogLevel": "DEBUG", | ||||||
|  |     "FileLogLevel": "TRACE" | ||||||
|  |   }, | ||||||
|  |   "BotLoggingSettings": { | ||||||
|  |     "Api": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "api.log", | ||||||
|  |       "ConsoleLogLevel": "TRACE", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     }, | ||||||
|  |     "Command": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "commands.log", | ||||||
|  |       "ConsoleLogLevel": "DEBUG", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     }, | ||||||
|  |     "Database": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "database.log", | ||||||
|  |       "ConsoleLogLevel": "DEBUG", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     }, | ||||||
|  |     "Message": { | ||||||
|  |       "Path": "logs/", | ||||||
|  |       "Filename": "message.log", | ||||||
|  |       "ConsoleLogLevel": "DEBUG", | ||||||
|  |       "FileLogLevel": "TRACE" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "DatabaseSettings": { | ||||||
|  |     "Host": "localhost", | ||||||
|  |     "User": "kd_kdb", | ||||||
|  |     "Password": "VGpZcihrb0N2T2MyZUlURQ==", | ||||||
|  |     "Database": "keksdose_bot_dev", | ||||||
|  |     "Charset": "utf8mb4", | ||||||
|  |     "UseUnicode": "true", | ||||||
|  |     "Buffered": "true", | ||||||
|  |     "AuthPlugin": "mysql_native_password" | ||||||
|  |   }, | ||||||
|  |   "DiscordBot": { | ||||||
|  |     "Token": "OTk4MTYwNDI3Njg5MTgxMjM3.GI7h67.BqD6Lu1Tz0MuG8iktYrcLnHi1pNozyMiWFGTKI", | ||||||
|  |     "Prefix": "!ke " | ||||||
|  |   }, | ||||||
|  |   "Bot": { | ||||||
|  |     "910199451145076828": { | ||||||
|  |       "MessageDeleteTimer": 2 | ||||||
|  |     }, | ||||||
|  |     "Technicians": [ | ||||||
|  |       240160344557879316 | ||||||
|  |     ], | ||||||
|  |     "WaitForRestart": 4, | ||||||
|  |     "WaitForShutdown": 4 | ||||||
|  |   }, | ||||||
|  |   "Base": { | ||||||
|  |     "910199451145076828": { | ||||||
|  |       "MaxVoiceStateHours": 24, | ||||||
|  |       "XpPerMessage": 2, | ||||||
|  |       "XpPerOntimeHour": 4, | ||||||
|  |       "AFKChannelIds": [ | ||||||
|  |         910199452915093593, | ||||||
|  |         910199452915093594 | ||||||
|  |       ], | ||||||
|  |       "AFKCommandChannelId": 910199452915093594, | ||||||
|  |       "HelpCommandReferenceUrl": "https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot/wiki/Befehle" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "BootLog": { | ||||||
|  |     "910199451145076828": { | ||||||
|  |       "LoginMessageChannelId": 910199452915093588 | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "Level": { | ||||||
|  |     "910199451145076828": { | ||||||
|  |       "ChangedLevelNotificationChannelId": 910199452667637892 | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "Permission": { | ||||||
|  |     "910199451145076828": { | ||||||
|  |       "AdminRoleIds": [ | ||||||
|  |         925072155203477584 | ||||||
|  |       ], | ||||||
|  |       "ModeratorRoleIds": [ | ||||||
|  |         925072209884635167 | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -12,6 +12,12 @@ | |||||||
|     "FileLogLevel": "INFO" |     "FileLogLevel": "INFO" | ||||||
|   }, |   }, | ||||||
|   "BotLoggingSettings": { |   "BotLoggingSettings": { | ||||||
|  |     "Api": { | ||||||
|  |       "Path": "logs/$date_now/", | ||||||
|  |       "Filename": "api.log", | ||||||
|  |       "ConsoleLogLevel": "ERROR", | ||||||
|  |       "FileLogLevel": "INFO" | ||||||
|  |     }, | ||||||
|     "Command": { |     "Command": { | ||||||
|       "Path": "logs/$date_now/", |       "Path": "logs/$date_now/", | ||||||
|       "Filename": "commands.log", |       "Filename": "commands.log", | ||||||
| @@ -38,9 +44,9 @@ | |||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "DatabaseSettings": { |   "DatabaseSettings": { | ||||||
|     "Host": "kdb_db_1", |     "Host": "kdb_db_prod_1", | ||||||
|     "User": "kd_kdb", |     "User": "kd_kdb", | ||||||
|     "Password": "a2Rfa2Ri", |     "Password": "Kz1nan0ow4RFYlJHNl9TJsO2fcO8PnphTlQ9ckV7X35tPHk=", | ||||||
|     "Database": "kd_kdb", |     "Database": "kd_kdb", | ||||||
|     "Port": "3306", |     "Port": "3306", | ||||||
|     "Charset": "utf8mb4", |     "Charset": "utf8mb4", | ||||||
| @@ -12,6 +12,12 @@ | |||||||
|     "FileLogLevel": "DEBUG" |     "FileLogLevel": "DEBUG" | ||||||
|   }, |   }, | ||||||
|   "BotLoggingSettings": { |   "BotLoggingSettings": { | ||||||
|  |     "Api": { | ||||||
|  |       "Path": "logs/$date_now/", | ||||||
|  |       "Filename": "api.log", | ||||||
|  |       "ConsoleLogLevel": "INFO", | ||||||
|  |       "FileLogLevel": "DEBUG" | ||||||
|  |     }, | ||||||
|     "Command": { |     "Command": { | ||||||
|       "Path": "logs/$date_now/", |       "Path": "logs/$date_now/", | ||||||
|       "Filename": "commands.log", |       "Filename": "commands.log", | ||||||
| @@ -38,9 +44,9 @@ | |||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "DatabaseSettings": { |   "DatabaseSettings": { | ||||||
|     "Host": "kdb_db_2", |     "Host": "kdb_db_staging_1", | ||||||
|     "User": "kd_kdb", |     "User": "kd_kdb", | ||||||
|     "Password": "a2Rfa2Ri", |     "Password": "MyZZd1ZNQ3fDvGI9TFV0N0LCp8OWc1k/S3J+WFJ0RCMmJmY=", | ||||||
|     "Database": "kd_kdb", |     "Database": "kd_kdb", | ||||||
|     "Port": "3306", |     "Port": "3306", | ||||||
|     "Charset": "utf8mb4", |     "Charset": "utf8mb4", | ||||||
| @@ -1,5 +1,6 @@ | |||||||
| { | { | ||||||
|   "FeatureFlags": { |   "FeatureFlags": { | ||||||
|  |     "ApiModule": false, | ||||||
|     "AdminModule": true, |     "AdminModule": true, | ||||||
|     "AutoRoleModule": true, |     "AutoRoleModule": true, | ||||||
|     "BaseModule": true, |     "BaseModule": true, | ||||||
| @@ -8,6 +9,7 @@ | |||||||
|     "CoreExtensionModule": true, |     "CoreExtensionModule": true, | ||||||
|     "DatabaseModule": true, |     "DatabaseModule": true, | ||||||
|     "ModeratorModule": true, |     "ModeratorModule": true, | ||||||
|  |     "LevelModule": true, | ||||||
|     "PermissionModule": true, |     "PermissionModule": true, | ||||||
|     "PresenceModule": true |     "PresenceModule": true | ||||||
|   } |   } | ||||||
| @@ -11,6 +11,7 @@ from bot.startup_discord_extension import StartupDiscordExtension | |||||||
| from bot.startup_migration_extension import StartupMigrationExtension | from bot.startup_migration_extension import StartupMigrationExtension | ||||||
| from bot.startup_module_extension import StartupModuleExtension | from bot.startup_module_extension import StartupModuleExtension | ||||||
| from bot.startup_settings_extension import StartupSettingsExtension | from bot.startup_settings_extension import StartupSettingsExtension | ||||||
|  | from bot_api.app_api_extension import AppApiExtension | ||||||
| from modules.boot_log.boot_log_extension import BootLogExtension | from modules.boot_log.boot_log_extension import BootLogExtension | ||||||
| from modules.database.database_extension import DatabaseExtension | from modules.database.database_extension import DatabaseExtension | ||||||
| 
 | 
 | ||||||
| @@ -29,6 +30,7 @@ class Program: | |||||||
|             .use_extension(StartupMigrationExtension) \ |             .use_extension(StartupMigrationExtension) \ | ||||||
|             .use_extension(BootLogExtension) \ |             .use_extension(BootLogExtension) \ | ||||||
|             .use_extension(DatabaseExtension) \ |             .use_extension(DatabaseExtension) \ | ||||||
|  |             .use_extension(AppApiExtension) \ | ||||||
|             .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() | ||||||
| @@ -1,15 +1,16 @@ | |||||||
| from cpl_query.extension import List | from cpl_query.extension import List | ||||||
| 
 | 
 | ||||||
|  | from bot_api.api_module import ApiModule | ||||||
| from bot_core.core_extension.core_extension_module import CoreExtensionModule | from bot_core.core_extension.core_extension_module import CoreExtensionModule | ||||||
| from bot_core.core_module import CoreModule | from bot_core.core_module import CoreModule | ||||||
| from bot_data.data_module import DataModule | from bot_data.data_module import DataModule | ||||||
| from modules.admin.admin_module import AdminModule |  | ||||||
| from modules.auto_role.auto_role_module import AutoRoleModule | from modules.auto_role.auto_role_module import AutoRoleModule | ||||||
| from modules.base.base_module import BaseModule | from modules.base.base_module import BaseModule | ||||||
| from modules.boot_log.boot_log_module import BootLogModule | from modules.boot_log.boot_log_module import BootLogModule | ||||||
| from modules.database.database_module import DatabaseModule | from modules.database.database_module import DatabaseModule | ||||||
| from modules.moderator.moderator_module import ModeratorModule | 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 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ModuleList: | class ModuleList: | ||||||
| @@ -20,12 +21,13 @@ class ModuleList: | |||||||
|         return List(type, [ |         return List(type, [ | ||||||
|             CoreModule,  # has to be first! |             CoreModule,  # has to be first! | ||||||
|             DataModule, |             DataModule, | ||||||
|             AdminModule, |  | ||||||
|             AutoRoleModule, |             AutoRoleModule, | ||||||
|             BaseModule, |             BaseModule, | ||||||
|             DatabaseModule, |             DatabaseModule, | ||||||
|             ModeratorModule, |             LevelModule, | ||||||
|             PermissionModule, |             PermissionModule, | ||||||
|  |             ApiModule, | ||||||
|  |             StatsModule, | ||||||
|             # has to be last! |             # has to be last! | ||||||
|             BootLogModule, |             BootLogModule, | ||||||
|             CoreExtensionModule, |             CoreExtensionModule, | ||||||
| @@ -9,6 +9,7 @@ from cpl_core.dependency_injection import ServiceProviderABC | |||||||
| from cpl_core.environment import ApplicationEnvironment | from cpl_core.environment import ApplicationEnvironment | ||||||
| from cpl_core.logging import LoggerABC | from cpl_core.logging import LoggerABC | ||||||
| 
 | 
 | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
| from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC | from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC | ||||||
| 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 | ||||||
| @@ -40,6 +41,9 @@ class Startup(StartupABC): | |||||||
|             services.add_singleton(CustomFileLoggerABC, DatabaseLogger) |             services.add_singleton(CustomFileLoggerABC, DatabaseLogger) | ||||||
|             services.add_singleton(CustomFileLoggerABC, MessageLogger) |             services.add_singleton(CustomFileLoggerABC, MessageLogger) | ||||||
| 
 | 
 | ||||||
|  |         if self._feature_flags.get_flag(FeatureFlagsEnum.api_module): | ||||||
|  |             services.add_singleton(CustomFileLoggerABC, ApiLogger) | ||||||
|  | 
 | ||||||
|         services.add_translation() |         services.add_translation() | ||||||
|         services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings)) |         services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings)) | ||||||
| 
 | 
 | ||||||
| @@ -4,8 +4,11 @@ from cpl_core.dependency_injection import ServiceCollectionABC | |||||||
| from cpl_core.environment import ApplicationEnvironmentABC | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
| 
 | 
 | ||||||
| from bot_data.abc.migration_abc import MigrationABC | from bot_data.abc.migration_abc import MigrationABC | ||||||
|  | from bot_data.migration.api_migration import ApiMigration | ||||||
| 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.stats_migration import StatsMigration | ||||||
| from bot_data.service.migration_service import MigrationService | from bot_data.service.migration_service import MigrationService | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @@ -21,3 +24,6 @@ class StartupMigrationExtension(StartupExtensionABC): | |||||||
|         services.add_transient(MigrationService) |         services.add_transient(MigrationService) | ||||||
|         services.add_transient(MigrationABC, InitialMigration) |         services.add_transient(MigrationABC, InitialMigration) | ||||||
|         services.add_transient(MigrationABC, AutoRoleMigration)  # 03.10.2022 #54 - 0.2.2 |         services.add_transient(MigrationABC, AutoRoleMigration)  # 03.10.2022 #54 - 0.2.2 | ||||||
|  |         services.add_transient(MigrationABC, ApiMigration)  # 15.10.2022 #70 - 0.3.0 | ||||||
|  |         services.add_transient(MigrationABC, LevelMigration)  # 06.11.2022 #25 - 0.3.0 | ||||||
|  |         services.add_transient(MigrationABC, StatsMigration)  # 09.11.2022 #46 - 0.3.0 | ||||||
| @@ -11,6 +11,7 @@ from bot_core.configuration.bot_logging_settings import BotLoggingSettings | |||||||
| from bot_core.configuration.bot_settings import BotSettings | from bot_core.configuration.bot_settings import BotSettings | ||||||
| from modules.base.configuration.base_settings import BaseSettings | from modules.base.configuration.base_settings import BaseSettings | ||||||
| from modules.boot_log.configuration.boot_log_settings import BootLogSettings | from modules.boot_log.configuration.boot_log_settings import BootLogSettings | ||||||
|  | from modules.level.configuration.level_settings import LevelSettings | ||||||
| from modules.permission.configuration.permission_settings import PermissionSettings | from modules.permission.configuration.permission_settings import PermissionSettings | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @@ -35,6 +36,7 @@ class StartupSettingsExtension(StartupExtensionABC): | |||||||
|         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, PermissionSettings, 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(configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key) |         self._configure_settings_with_sub_settings(configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key) | ||||||
| 
 | 
 | ||||||
| @@ -45,6 +45,30 @@ | |||||||
|       "no_entry_point_error": "Fehler: Kein Eintrittspunkt!", |       "no_entry_point_error": "Fehler: Kein Eintrittspunkt!", | ||||||
|       "extension_failed": "Fehler: Erweiterung ist fehlgeschlagen!", |       "extension_failed": "Fehler: Erweiterung ist fehlgeschlagen!", | ||||||
|       "bot_not_ready_yet": "Ey Alter! Gedulde dich doch mal! ..." |       "bot_not_ready_yet": "Ey Alter! Gedulde dich doch mal! ..." | ||||||
|  |     }, | ||||||
|  |     "colors": { | ||||||
|  |       "blue": "Blau", | ||||||
|  |       "dark_blue": "Dunkelblau", | ||||||
|  |       "dark_gold": "Dunkelgold", | ||||||
|  |       "dark_gray": "Dunkelgrau", | ||||||
|  |       "dark_green": "Dunkelgrün", | ||||||
|  |       "dark_grey": "Dunkelgrau", | ||||||
|  |       "dark_magenta": "Dunkelmagenta", | ||||||
|  |       "dark_orange": "Dunkelorange", | ||||||
|  |       "dark_purple": "Dunkelviolett", | ||||||
|  |       "dark_red": "Dunkelrot", | ||||||
|  |       "dark_teal": "Dunkelblaugrün", | ||||||
|  |       "default": "Standard", | ||||||
|  |       "gold": "Gold", | ||||||
|  |       "green": "Grün", | ||||||
|  |       "greyple": "Graugrün", | ||||||
|  |       "light_grey": "Hellgrau", | ||||||
|  |       "magenta": "Magenta", | ||||||
|  |       "orange": "Orange", | ||||||
|  |       "purple": "Violett", | ||||||
|  |       "red": "Rot", | ||||||
|  |       "teal": "Blaugrün", | ||||||
|  |       "yellow": "Gelb" | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   "modules": { |   "modules": { | ||||||
| @@ -138,6 +162,7 @@ | |||||||
|           "discord_join": "Discord beigetreten am", |           "discord_join": "Discord beigetreten am", | ||||||
|           "last_join": "Server beigetreten am", |           "last_join": "Server beigetreten am", | ||||||
|           "xp": "XP", |           "xp": "XP", | ||||||
|  |           "ontime": "Ontime", | ||||||
|           "roles": "Rollen", |           "roles": "Rollen", | ||||||
|           "joins": "Beitritte", |           "joins": "Beitritte", | ||||||
|           "lefts": "Abgänge", |           "lefts": "Abgänge", | ||||||
| @@ -149,8 +174,95 @@ | |||||||
|     "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": { | ||||||
|  |       "new_level_message": "<@{}> ist nun Level {}", | ||||||
|  |       "seeding_started": "Levelsystem wird neu geladen.", | ||||||
|  |       "seeding_failed": "Levelsystem konnte nicht neu geladen werden.", | ||||||
|  |       "seeding_finished": "Levelsystem wurde Erfolgreich neu geladen.", | ||||||
|  |       "error": { | ||||||
|  |         "nothing_found": "Keine Level Einträge gefunden.", | ||||||
|  |         "level_with_name_already_exists": "Ein Level mit dem Namen {} existiert bereits!", | ||||||
|  |         "level_with_xp_already_exists": "Das Level {} hat bereits die Mindest XP {}!" | ||||||
|  |       }, | ||||||
|  |       "list": { | ||||||
|  |         "title": "Level:", | ||||||
|  |         "description": "Konfigurierte Level:", | ||||||
|  |         "name": "Name", | ||||||
|  |         "min_xp": "Mindest XP", | ||||||
|  |         "permission_int": "Berechtigungen" | ||||||
|  |       }, | ||||||
|  |       "create": { | ||||||
|  |         "created": "Level {} mit Berechtigungen {} wurde erstellt." | ||||||
|  |       }, | ||||||
|  |       "remove": { | ||||||
|  |         "success": "Level {} wurde entfernt :D", | ||||||
|  |         "error": { | ||||||
|  |           "not_found": "Level {} nicht gefunden!" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "down": { | ||||||
|  |         "already_first": "{} hat bereits das erste Level.", | ||||||
|  |         "success": "{} wurde auf Level {} runtergesetzt :)", | ||||||
|  |         "failed": "{} konnte nicht runtergesetzt werden :(" | ||||||
|  |       }, | ||||||
|  |       "up": { | ||||||
|  |         "already_last": "{} hat bereits das höchste Level.", | ||||||
|  |         "success": "{} wurde auf Level {} hochgesetzt :)", | ||||||
|  |         "failed": "{} konnte nicht hochgesetzt werden :(" | ||||||
|  |       }, | ||||||
|  |       "set": { | ||||||
|  |         "already_level": "{} hat bereits das Level {} :/", | ||||||
|  |         "success": "{} ist nun Level {} :)", | ||||||
|  |         "failed": "Das Level von {} konnte nicht auf {} gesetzt werden :(", | ||||||
|  |         "not_found": "Das Level {} konnte nicht gefunden werden :(" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "database": {}, |     "database": {}, | ||||||
|     "permission": { |     "permission": {}, | ||||||
|  |     "stats": { | ||||||
|  |       "list": { | ||||||
|  |         "statistic": "Statistik", | ||||||
|  |         "description": "Beschreibung", | ||||||
|  |         "nothing_found": "Keine Statistiken gefunden." | ||||||
|  |       }, | ||||||
|  |       "view": { | ||||||
|  |         "statistic": "Statistik", | ||||||
|  |         "description": "Beschreibung", | ||||||
|  |         "failed": "Statistik kann nicht gezeigt werden :(" | ||||||
|  |       }, | ||||||
|  |       "add": { | ||||||
|  |         "failed": "Statistik kann nicht hinzugefügt werden :(", | ||||||
|  |         "success": "Statistik wurde hinzugefügt :D" | ||||||
|  |       }, | ||||||
|  |       "edit": { | ||||||
|  |         "failed": "Statistik kann nicht bearbeitet werden :(", | ||||||
|  |         "success": "Statistik wurde gespeichert :D" | ||||||
|  |       }, | ||||||
|  |       "remove": { | ||||||
|  |         "failed": "Statistik kann nicht gelöscht werden :(", | ||||||
|  |         "success": "Statistik wurde gelöscht :D" | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "api": { | ||||||
|  |     "mail": { | ||||||
|  |       "automatic_mail": "\n\nDies ist eine automatische E-Mail.\nGesendet von {}-{}@{}" | ||||||
|  |     }, | ||||||
|  |     "api": { | ||||||
|  |       "test_mail": { | ||||||
|  |         "subject": "Krümmelmonster Web Interface Test-Mail", | ||||||
|  |         "message": "Dies ist eine Test-Mail vom Krümmelmonster Web Interface\nGesendet von {}-{}" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "auth": { | ||||||
|  |       "confirmation": { | ||||||
|  |         "subject": "E-Mail für {} {} bestätigen", | ||||||
|  |         "message": "Öffne den Link um die E-Mail zu bestätigen:\n{}auth/register/{}" | ||||||
|  |       }, | ||||||
|  |       "forgot_password": { | ||||||
|  |         "subject": "Passwort für {} {} zurücksetzen", | ||||||
|  |         "message": "Öffne den Link um das Passwort zu ändern:\n{}auth/forgot-password/{}" | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -11,11 +11,11 @@ Discord bot  for the Keksdose discord Server | |||||||
| 
 | 
 | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| __title__ = 'modules.admin' | __title__ = 'bot_api' | ||||||
| __author__ = 'Sven Heidemann' | __author__ = 'Sven Heidemann' | ||||||
| __license__ = 'MIT' | __license__ = 'MIT' | ||||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
| __version__ = '0.2.3' | __version__ = '0.3.dev25' | ||||||
| 
 | 
 | ||||||
| from collections import namedtuple | from collections import namedtuple | ||||||
| 
 | 
 | ||||||
| @@ -23,4 +23,4 @@ from collections import namedtuple | |||||||
| # imports:  | # imports:  | ||||||
| 
 | 
 | ||||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
| version_info = VersionInfo(major='0', minor='2', micro='3') | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/abc/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.service' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										89
									
								
								kdb-bot/src/bot_api/abc/auth_service_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								kdb-bot/src/bot_api/abc/auth_service_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | from abc import ABC, abstractmethod | ||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | from cpl_query.extension import List | ||||||
|  |  | ||||||
|  | from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria | ||||||
|  | from bot_api.model.auth_user_dto import AuthUserDTO | ||||||
|  | from bot_api.model.auth_user_filtered_result_dto import AuthUserFilteredResultDTO | ||||||
|  | from bot_api.model.email_string_dto import EMailStringDTO | ||||||
|  | from bot_api.model.o_auth_dto import OAuthDTO | ||||||
|  | from bot_api.model.reset_password_dto import ResetPasswordDTO | ||||||
|  | from bot_api.model.token_dto import TokenDTO | ||||||
|  | from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO | ||||||
|  | from bot_data.model.auth_user import AuthUser | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthServiceABC(ABC): | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def __init__(self): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def generate_token(self, user: AuthUser) -> str: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def decode_token(self, token: str) -> dict: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def get_decoded_token_from_request(self) -> dict: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def find_decoded_token_from_request(self) -> Optional[dict]: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def get_all_auth_users_async(self) -> List[AuthUserDTO]: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def find_auth_user_by_email_async(self, email: str) -> AuthUserDTO: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def add_auth_user_async(self, user_dto: AuthUserDTO): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def add_auth_user_by_oauth_async(self, dto: OAuthDTO): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def delete_auth_user_by_email_async(self, email: str): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def delete_auth_user_async(self, user_dto: AuthUserDTO): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def verify_login(self, token_str: str) -> bool: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def revoke_async(self, token_dto: TokenDTO): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def confirm_email_async(self, id: str) -> bool: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def forgot_password_async(self, email: str): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def confirm_forgot_password_async(self, id: str) -> EMailStringDTO: pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     async def reset_password_async(self, rp_dto: ResetPasswordDTO): pass | ||||||
							
								
								
									
										13
									
								
								kdb-bot/src/bot_api/abc/dto_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								kdb-bot/src/bot_api/abc/dto_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | from abc import ABC, abstractmethod | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DtoABC(ABC): | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def __init__(self): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def from_dict(self, values: dict): pass | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def to_dict(self) -> dict: pass | ||||||
							
								
								
									
										17
									
								
								kdb-bot/src/bot_api/abc/select_criteria_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								kdb-bot/src/bot_api/abc/select_criteria_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | from abc import ABC, abstractmethod | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SelectCriteriaABC(ABC): | ||||||
|  |  | ||||||
|  |     @abstractmethod | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             page_index: int, | ||||||
|  |             page_size: int, | ||||||
|  |             sort_direction: str, | ||||||
|  |             sort_column: str | ||||||
|  |     ): | ||||||
|  |         self.page_index = page_index | ||||||
|  |         self.page_size = page_size | ||||||
|  |         self.sort_direction = sort_direction | ||||||
|  |         self.sort_column = sort_column | ||||||
							
								
								
									
										16
									
								
								kdb-bot/src/bot_api/abc/transformer_abc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								kdb-bot/src/bot_api/abc/transformer_abc.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | from abc import abstractmethod | ||||||
|  |  | ||||||
|  | from cpl_core.database import TableABC | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TransformerABC: | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     @abstractmethod | ||||||
|  |     def to_db(dto: DtoABC) -> TableABC: pass | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     @abstractmethod | ||||||
|  |     def to_dto(db: TableABC) -> DtoABC: pass | ||||||
							
								
								
									
										156
									
								
								kdb-bot/src/bot_api/api.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								kdb-bot/src/bot_api/api.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | |||||||
|  | import re | ||||||
|  | import sys | ||||||
|  | import textwrap | ||||||
|  | import uuid | ||||||
|  | from functools import partial | ||||||
|  | from typing import Union | ||||||
|  |  | ||||||
|  | import eventlet | ||||||
|  | from cpl_core.dependency_injection import ServiceProviderABC | ||||||
|  | from cpl_core.utils import CredentialManager | ||||||
|  | from eventlet import wsgi | ||||||
|  | from flask import Flask, request, jsonify, Response | ||||||
|  | from flask_cors import CORS | ||||||
|  | from flask_socketio import SocketIO | ||||||
|  | from werkzeug.exceptions import NotFound | ||||||
|  |  | ||||||
|  | from bot_api.configuration.api_settings import ApiSettings | ||||||
|  | from bot_api.configuration.authentication_settings import AuthenticationSettings | ||||||
|  | from bot_api.configuration.frontend_settings import FrontendSettings | ||||||
|  | from bot_api.exception.service_error_code_enum import ServiceErrorCode | ||||||
|  | from bot_api.exception.service_exception import ServiceException | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
|  | from bot_api.model.error_dto import ErrorDTO | ||||||
|  | from bot_api.route.route import Route | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Api(Flask): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             logger: ApiLogger, | ||||||
|  |             services: ServiceProviderABC, | ||||||
|  |             api_settings: ApiSettings, | ||||||
|  |             frontend_settings: FrontendSettings, | ||||||
|  |             auth_settings: AuthenticationSettings, | ||||||
|  |             *args, **kwargs | ||||||
|  |     ): | ||||||
|  |         if not args: | ||||||
|  |             kwargs.setdefault('import_name', __name__) | ||||||
|  |  | ||||||
|  |         Flask.__init__(self, *args, **kwargs) | ||||||
|  |  | ||||||
|  |         self._logger = logger | ||||||
|  |         self._services = services | ||||||
|  |         self._api_settings = api_settings | ||||||
|  |         self._auth_settings = auth_settings | ||||||
|  |  | ||||||
|  |         self._cors = CORS(self, support_credentials=True) | ||||||
|  |  | ||||||
|  |         # register hooks | ||||||
|  |         self.before_request(self.before_request_hook) | ||||||
|  |         self.after_request(self.after_request_hook) | ||||||
|  |  | ||||||
|  |         # register error handler | ||||||
|  |         exc_class, code = self._get_exc_class_and_code(Exception) | ||||||
|  |         self.register_error_handler(exc_class, self.handle_exception) | ||||||
|  |  | ||||||
|  |         # websockets | ||||||
|  |         self._socketio = SocketIO(self, cors_allowed_origins='*', path='/api/socket.io') | ||||||
|  |         self._socketio.on_event('connect', self.on_connect) | ||||||
|  |         self._socketio.on_event('disconnect', self.on_disconnect) | ||||||
|  |  | ||||||
|  |         self._requests = {} | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def _get_methods_from_registered_route() -> Union[list[str], str]: | ||||||
|  |         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]: | ||||||
|  |             methods = Route.registered_routes[request.path][1]['methods'] | ||||||
|  |  | ||||||
|  |         if len(methods) == 1: | ||||||
|  |             return methods[0] | ||||||
|  |         return methods | ||||||
|  |  | ||||||
|  |     def _register_routes(self): | ||||||
|  |         for path, f in Route.registered_routes.items(): | ||||||
|  |             route = f[0] | ||||||
|  |             kwargs = f[1] | ||||||
|  |             cls = None | ||||||
|  |             qual_name_split = route.__qualname__.split('.') | ||||||
|  |             if len(qual_name_split) > 0: | ||||||
|  |                 cls_type = vars(sys.modules[route.__module__])[qual_name_split[0]] | ||||||
|  |                 cls = self._services.get_service(cls_type) | ||||||
|  |  | ||||||
|  |             partial_f = partial(route, self if cls is None else cls) | ||||||
|  |             partial_f.__name__ = route.__name__ | ||||||
|  |             self.route(path, **kwargs)(partial_f) | ||||||
|  |  | ||||||
|  |     def handle_exception(self, e: Exception): | ||||||
|  |         self._logger.error(__name__, f'Caught error', e) | ||||||
|  |  | ||||||
|  |         if isinstance(e, ServiceException): | ||||||
|  |             ex: ServiceException = e | ||||||
|  |             self._logger.error(__name__, ex.get_detailed_message()) | ||||||
|  |             error = ErrorDTO(ex.error_code, ex.message) | ||||||
|  |             return jsonify(error.to_dict()), 500 | ||||||
|  |         elif isinstance(e, NotFound): | ||||||
|  |             self._logger.error(__name__, e.description) | ||||||
|  |             error = ErrorDTO(ServiceErrorCode.NotFound, e.description) | ||||||
|  |             return jsonify(error.to_dict()), 404 | ||||||
|  |         else: | ||||||
|  |             tracking_id = uuid.uuid4() | ||||||
|  |             user_message = f'Tracking Id: {tracking_id}' | ||||||
|  |             self._logger.error(__name__, user_message, e) | ||||||
|  |             error = ErrorDTO(None, user_message) | ||||||
|  |             return jsonify(error.to_dict()), 400 | ||||||
|  |  | ||||||
|  |     def before_request_hook(self): | ||||||
|  |         request_id = uuid.uuid4() | ||||||
|  |         self._requests[request] = request_id | ||||||
|  |         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}') | ||||||
|  |  | ||||||
|  |         headers = str(request.headers).replace('\n', '\n\t\t') | ||||||
|  |         data = request.get_data() | ||||||
|  |         data = '' if len(data) == 0 else str(data.decode(encoding="utf-8")) | ||||||
|  |  | ||||||
|  |         text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tUser-Agent: {request.user_agent.string}\n\tBody: {data}') | ||||||
|  |         self._logger.trace(__name__, text) | ||||||
|  |  | ||||||
|  |     def after_request_hook(self, response: Response): | ||||||
|  |         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}' | ||||||
|  |         if request in self._requests: | ||||||
|  |             request_id = self._requests[request] | ||||||
|  |  | ||||||
|  |         self._logger.info(__name__, f'Answered {request_id}') | ||||||
|  |  | ||||||
|  |         headers = str(request.headers).replace('\n', '\n\t\t') | ||||||
|  |         data = request.get_data() | ||||||
|  |         data = '' if len(data) == 0 else str(data.decode(encoding="utf-8")) | ||||||
|  |  | ||||||
|  |         text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}') | ||||||
|  |         self._logger.trace(__name__, text) | ||||||
|  |  | ||||||
|  |         return response | ||||||
|  |  | ||||||
|  |     def start(self): | ||||||
|  |         self._logger.info(__name__, f'Starting API {self._api_settings.host}:{self._api_settings.port}') | ||||||
|  |         self._register_routes() | ||||||
|  |         self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key) | ||||||
|  |         # from waitress import serve | ||||||
|  |         # https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html | ||||||
|  |         # serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10) | ||||||
|  |         wsgi.server( | ||||||
|  |             eventlet.listen((self._api_settings.host, self._api_settings.port)), | ||||||
|  |             self, | ||||||
|  |             log_output=False | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def on_connect(self): | ||||||
|  |         self._logger.info(__name__, f'Client connected') | ||||||
|  |  | ||||||
|  |     def on_disconnect(self): | ||||||
|  |         self._logger.info(__name__, f'Client disconnected') | ||||||
							
								
								
									
										52
									
								
								kdb-bot/src/bot_api/api_module.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								kdb-bot/src/bot_api/api_module.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | import os | ||||||
|  |  | ||||||
|  | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.dependency_injection import ServiceCollectionABC | ||||||
|  | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
|  | from cpl_core.mailing import EMailClientABC, EMailClient | ||||||
|  | from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum | ||||||
|  | from cpl_discord.service.discord_collection_abc import DiscordCollectionABC | ||||||
|  | from flask import Flask | ||||||
|  |  | ||||||
|  | from bot_api.abc.auth_service_abc import AuthServiceABC | ||||||
|  | from bot_api.api import Api | ||||||
|  | from bot_api.api_thread import ApiThread | ||||||
|  | from bot_api.controller.auth_controller import AuthController | ||||||
|  | from bot_api.controller.auth_discord_controller import AuthDiscordController | ||||||
|  | from bot_api.controller.discord.server_controller import ServerController | ||||||
|  | from bot_api.controller.gui_controller import GuiController | ||||||
|  | from bot_api.event.bot_api_on_ready_event import BotApiOnReadyEvent | ||||||
|  | from bot_api.service.auth_service import AuthService | ||||||
|  | from bot_api.service.discord_service import DiscordService | ||||||
|  | from bot_core.abc.module_abc import ModuleABC | ||||||
|  | from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ApiModule(ModuleABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, dc: DiscordCollectionABC): | ||||||
|  |         ModuleABC.__init__(self, dc, FeatureFlagsEnum.api_module) | ||||||
|  |  | ||||||
|  |     def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): | ||||||
|  |         cwd = env.working_directory | ||||||
|  |         env.set_working_directory(os.path.dirname(os.path.realpath(__file__))) | ||||||
|  |         config.add_json_file(f'config/apisettings.json', optional=False) | ||||||
|  |         config.add_json_file(f'config/apisettings.{env.environment_name}.json', optional=True) | ||||||
|  |         config.add_json_file(f'config/apisettings.{env.host_name}.json', optional=True) | ||||||
|  |         env.set_working_directory(cwd) | ||||||
|  |  | ||||||
|  |     def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): | ||||||
|  |         services.add_singleton(EMailClientABC, EMailClient) | ||||||
|  |  | ||||||
|  |         services.add_singleton(ApiThread) | ||||||
|  |         services.add_singleton(Flask, Api) | ||||||
|  |  | ||||||
|  |         services.add_transient(AuthServiceABC, AuthService) | ||||||
|  |         services.add_transient(AuthController) | ||||||
|  |         services.add_transient(AuthDiscordController) | ||||||
|  |         services.add_transient(GuiController) | ||||||
|  |         services.add_transient(DiscordService) | ||||||
|  |         services.add_transient(ServerController) | ||||||
|  |  | ||||||
|  |         # cpl-discord | ||||||
|  |         self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent) | ||||||
							
								
								
									
										24
									
								
								kdb-bot/src/bot_api/api_thread.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								kdb-bot/src/bot_api/api_thread.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | import threading | ||||||
|  |  | ||||||
|  | from bot_api.api import Api | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ApiThread(threading.Thread): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             logger: ApiLogger, | ||||||
|  |             api: Api | ||||||
|  |     ): | ||||||
|  |         threading.Thread.__init__(self, daemon=True) | ||||||
|  |  | ||||||
|  |         self._logger = logger | ||||||
|  |         self._api = api | ||||||
|  |  | ||||||
|  |     def run(self) -> None: | ||||||
|  |         try: | ||||||
|  |             self._logger.trace(__name__, f'Try to start {type(self._api).__name__}') | ||||||
|  |             self._api.start() | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, 'Start failed', e) | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/app_api_extension.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/app_api_extension.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | from cpl_core.application import ApplicationExtensionABC | ||||||
|  | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.dependency_injection import ServiceProviderABC | ||||||
|  |  | ||||||
|  | from bot_api.abc.auth_service_abc import AuthServiceABC | ||||||
|  | from bot_api.configuration.authentication_settings import AuthenticationSettings | ||||||
|  | from bot_api.route.route import Route | ||||||
|  | from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum | ||||||
|  | from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings | ||||||
|  | from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AppApiExtension(ApplicationExtensionABC): | ||||||
|  |  | ||||||
|  |     def __init__(self): | ||||||
|  |         ApplicationExtensionABC.__init__(self) | ||||||
|  |  | ||||||
|  |     async def run(self, config: ConfigurationABC, services: ServiceProviderABC): | ||||||
|  |         feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings) | ||||||
|  |         if not feature_flags.get_flag(FeatureFlagsEnum.api_module): | ||||||
|  |             return | ||||||
|  |  | ||||||
|  |         auth_settings: AuthenticationSettings = config.get_configuration(AuthenticationSettings) | ||||||
|  |         auth_users: AuthUserRepositoryABC = services.get_service(AuthUserRepositoryABC) | ||||||
|  |         auth: AuthServiceABC = services.get_service(AuthServiceABC) | ||||||
|  |         Route.init_authorize(auth_users, auth) | ||||||
							
								
								
									
										44
									
								
								kdb-bot/src/bot_api/bot-api.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								kdb-bot/src/bot_api/bot-api.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | { | ||||||
|  |   "ProjectSettings": { | ||||||
|  |     "Name": "bot-api", | ||||||
|  |     "Version": { | ||||||
|  |       "Major": "0", | ||||||
|  |       "Minor": "3", | ||||||
|  |       "Micro": "dev70" | ||||||
|  |     }, | ||||||
|  |     "Author": "", | ||||||
|  |     "AuthorEmail": "", | ||||||
|  |     "Description": "", | ||||||
|  |     "LongDescription": "", | ||||||
|  |     "URL": "", | ||||||
|  |     "CopyrightDate": "", | ||||||
|  |     "CopyrightName": "", | ||||||
|  |     "LicenseName": "", | ||||||
|  |     "LicenseDescription": "", | ||||||
|  |     "Dependencies": [ | ||||||
|  |       "cpl-core==2022.10.0.post7" | ||||||
|  |     ], | ||||||
|  |     "DevDependencies": [ | ||||||
|  |       "cpl-cli==2022.10.0" | ||||||
|  |     ], | ||||||
|  |     "PythonVersion": ">=3.10.4", | ||||||
|  |     "PythonPath": {}, | ||||||
|  |     "Classifiers": [] | ||||||
|  |   }, | ||||||
|  |   "BuildSettings": { | ||||||
|  |     "ProjectType": "library", | ||||||
|  |     "SourcePath": "", | ||||||
|  |     "OutputPath": "../../dist", | ||||||
|  |     "Main": "bot_api.main", | ||||||
|  |     "EntryPoint": "bot-api", | ||||||
|  |     "IncludePackageData": false, | ||||||
|  |     "Included": [], | ||||||
|  |     "Excluded": [ | ||||||
|  |       "*/__pycache__", | ||||||
|  |       "*/logs", | ||||||
|  |       "*/tests" | ||||||
|  |     ], | ||||||
|  |     "PackageData": {}, | ||||||
|  |     "ProjectReferences": [] | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								kdb-bot/src/bot_api/config/apisettings.development.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								kdb-bot/src/bot_api/config/apisettings.development.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | { | ||||||
|  |   "Api": { | ||||||
|  |     "Port": 80, | ||||||
|  |     "Host": "0.0.0.0", | ||||||
|  |     "RedirectToHTTPS": false | ||||||
|  |   }, | ||||||
|  |   "Authentication": { | ||||||
|  |     "SecretKey": "RjNiNUxEeisjSnZ6Zz1XIUBnc2EleHNG", | ||||||
|  |     "Issuer": "http://localhost:8044", | ||||||
|  |     "Audience": "http://localhost:8043", | ||||||
|  |     "TokenExpireTime": 1, | ||||||
|  |     "RefreshTokenExpireTime": 7 | ||||||
|  |   }, | ||||||
|  |   "DiscordAuthentication": { | ||||||
|  |     "ClientSecret": "cmhqYmF4MXBCd2IzeEZoSXRZQ29vY3NwUWwxQzFTZng=", | ||||||
|  |     "RedirectURL": "http://localhost:8043/auth/register", | ||||||
|  |     "Scope": [ | ||||||
|  |       "identify", | ||||||
|  |       "email" | ||||||
|  |     ], | ||||||
|  |     "TokenURL": "https://discordapp.com/api/oauth2/token", | ||||||
|  |     "AuthURL": "https://discordapp.com/api/oauth2/authorize" | ||||||
|  |   }, | ||||||
|  |   "Frontend": { | ||||||
|  |     "URL": "http://localhost:8043/" | ||||||
|  |   }, | ||||||
|  |   "EMailClientSettings": { | ||||||
|  |     "Host": "mail.sh-edraft.de", | ||||||
|  |     "Port": "587", | ||||||
|  |     "UserName": "dev-srv@sh-edraft.de", | ||||||
|  |     "Credentials": "RmBOQX1eNFYiYjgsSid3fV1nelc2WA==" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										28
									
								
								kdb-bot/src/bot_api/config/apisettings.edrafts-lapi.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								kdb-bot/src/bot_api/config/apisettings.edrafts-lapi.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | { | ||||||
|  |   "Api": { | ||||||
|  |     "Port": 5000, | ||||||
|  |     "Host": "0.0.0.0", | ||||||
|  |     "RedirectToHTTPS": false | ||||||
|  |   }, | ||||||
|  |   "Authentication": { | ||||||
|  |     "SecretKey": "RjNiNUxEeisjSnZ6Zz1XIUBnc2EleHNG", | ||||||
|  |     "Issuer": "http://localhost:5000", | ||||||
|  |     "Audience": "http://localhost:4200", | ||||||
|  |     "TokenExpireTime": 1, | ||||||
|  |     "RefreshTokenExpireTime": 7 | ||||||
|  |   }, | ||||||
|  |   "DiscordAuthentication": { | ||||||
|  |     "ClientSecret": "V3FTb3JYVFBiVktEeHZxdWJDWW4xcnBCbXRwdmpwcy0=", | ||||||
|  |     "_RedirectURL": "http://localhost:5000/api/auth/discord/register", | ||||||
|  |     "RedirectURL": "http://localhost:4200/auth/register", | ||||||
|  |     "Scope": [ | ||||||
|  |       "identify", | ||||||
|  |       "email" | ||||||
|  |     ], | ||||||
|  |     "TokenURL": "https://discordapp.com/api/oauth2/token", | ||||||
|  |     "AuthURL": "https://discordapp.com/api/oauth2/authorize" | ||||||
|  |   }, | ||||||
|  |   "Frontend": { | ||||||
|  |     "URL": "http://localhost:4200/" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								kdb-bot/src/bot_api/config/apisettings.edrafts-pc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								kdb-bot/src/bot_api/config/apisettings.edrafts-pc.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | { | ||||||
|  |   "Api": { | ||||||
|  |     "Port": 8044, | ||||||
|  |     "Host": "0.0.0.0", | ||||||
|  |     "RedirectToHTTPS": false | ||||||
|  |   }, | ||||||
|  |   "Authentication": { | ||||||
|  |     "SecretKey": "RjNiNUxEeisjSnZ6Zz1XIUBnc2EleHNG", | ||||||
|  |     "Issuer": "http://localhost:8084", | ||||||
|  |     "Audience": "http://localhost:4200", | ||||||
|  |     "TokenExpireTime": 1, | ||||||
|  |     "RefreshTokenExpireTime": 7 | ||||||
|  |   }, | ||||||
|  |   "DiscordAuthentication": { | ||||||
|  |     "ClientSecret": "V3FTb3JYVFBiVktEeHZxdWJDWW4xcnBCbXRwdmpwcy0=", | ||||||
|  |     "RedirectURL": "http://localhost:4200/auth/register", | ||||||
|  |     "Scope": [ | ||||||
|  |       "identify", | ||||||
|  |       "email" | ||||||
|  |     ], | ||||||
|  |     "TokenURL": "https://discordapp.com/api/oauth2/token", | ||||||
|  |     "AuthURL": "https://discordapp.com/api/oauth2/authorize" | ||||||
|  |   }, | ||||||
|  |   "Frontend": { | ||||||
|  |     "URL": "http://localhost:4200/" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								kdb-bot/src/bot_api/config/apisettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								kdb-bot/src/bot_api/config/apisettings.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | {} | ||||||
							
								
								
									
										33
									
								
								kdb-bot/src/bot_api/config/apisettings.production.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								kdb-bot/src/bot_api/config/apisettings.production.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | { | ||||||
|  |   "Api": { | ||||||
|  |     "Port": 80, | ||||||
|  |     "Host": "0.0.0.0", | ||||||
|  |     "RedirectToHTTPS": false | ||||||
|  |   }, | ||||||
|  |   "Authentication": { | ||||||
|  |     "SecretKey": "cEwzW2BdcWxGLTBdPClJImNIbDFJXjVsPGw=", | ||||||
|  |     "Issuer": "https://kdb.keksdose-gaming.de/", | ||||||
|  |     "Audience": "https://kdb.keksdose-gaming.de/", | ||||||
|  |     "TokenExpireTime": 1, | ||||||
|  |     "RefreshTokenExpireTime": 7 | ||||||
|  |   }, | ||||||
|  |   "DiscordAuthentication": { | ||||||
|  |     "ClientSecret": "SXpIOGY4ZzhWVEljOXJwSk5QcVpNU0lmRDNTb2c1Vk8=", | ||||||
|  |     "RedirectURL": "https://kdb.keksdose-gaming.de/auth/register", | ||||||
|  |     "Scope": [ | ||||||
|  |       "identify", | ||||||
|  |       "email" | ||||||
|  |     ], | ||||||
|  |     "TokenURL": "https://discordapp.com/api/oauth2/token", | ||||||
|  |     "AuthURL": "https://discordapp.com/api/oauth2/authorize" | ||||||
|  |   }, | ||||||
|  |   "Frontend": { | ||||||
|  |     "URL": "https://kdb.keksdose-gaming.de/" | ||||||
|  |   }, | ||||||
|  |   "EMailClientSettings": { | ||||||
|  |     "Host": "mail.sh-edraft.de", | ||||||
|  |     "Port": "587", | ||||||
|  |     "UserName": "kruemmelmonster@sh-edraft.de", | ||||||
|  |     "Credentials": "YjAwT3tPSVspezdadExdOEkoV3M3XiNb" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								kdb-bot/src/bot_api/config/apisettings.staging.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								kdb-bot/src/bot_api/config/apisettings.staging.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | { | ||||||
|  |   "Api": { | ||||||
|  |     "Port": 80, | ||||||
|  |     "Host": "0.0.0.0", | ||||||
|  |     "RedirectToHTTPS": false | ||||||
|  |   }, | ||||||
|  |   "Authentication": { | ||||||
|  |     "SecretKey": "Kj87RjklLUM1MytsUjtbcCswRidBV2VdMXU=", | ||||||
|  |     "Issuer": "https://kdb-test.keksdose-gaming.de/", | ||||||
|  |     "Audience": "https://kdb-test.keksdose-gaming.de/", | ||||||
|  |     "TokenExpireTime": 1, | ||||||
|  |     "RefreshTokenExpireTime": 7 | ||||||
|  |   }, | ||||||
|  |   "DiscordAuthentication": { | ||||||
|  |     "ClientSecret": "VVdRZTg1SnFxUExCNmhzU1RZY05mTHV5TmVaV0NkUmc=", | ||||||
|  |     "RedirectURL": "https://kdb-test.keksdose-gaming.de/auth/register", | ||||||
|  |     "Scope": [ | ||||||
|  |       "identify", | ||||||
|  |       "email" | ||||||
|  |     ], | ||||||
|  |     "TokenURL": "https://discordapp.com/api/oauth2/token", | ||||||
|  |     "AuthURL": "https://discordapp.com/api/oauth2/authorize" | ||||||
|  |   }, | ||||||
|  |   "Frontend": { | ||||||
|  |     "URL": "https://kdb-test.keksdose-gaming.de/" | ||||||
|  |   }, | ||||||
|  |   "EMailClientSettings": { | ||||||
|  |     "Host": "mail.sh-edraft.de", | ||||||
|  |     "Port": "587", | ||||||
|  |     "UserName": "kruemmelmonster@sh-edraft.de", | ||||||
|  |     "Credentials": "YjAwT3tPSVspezdadExdOEkoV3M3XiNb" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								kdb-bot/src/bot_api/config/appsettings.PC-Nick.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								kdb-bot/src/bot_api/config/appsettings.PC-Nick.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | {} | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/configuration/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.configuration' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										35
									
								
								kdb-bot/src/bot_api/configuration/api_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								kdb-bot/src/bot_api/configuration/api_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ApiSettings(ConfigurationModelABC): | ||||||
|  |  | ||||||
|  |     def __init__(self): | ||||||
|  |         ConfigurationModelABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._port = 80 | ||||||
|  |         self._host = '' | ||||||
|  |         self._redirect_to_https = False | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def port(self) -> int: | ||||||
|  |         return self._port | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def host(self) -> str: | ||||||
|  |         return self._host | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def redirect_to_https(self) -> bool: | ||||||
|  |         return self._redirect_to_https | ||||||
|  |  | ||||||
|  |     def from_dict(self, settings: dict): | ||||||
|  |         try: | ||||||
|  |             self._port = int(settings['Port']) | ||||||
|  |             self._host = settings['Host'] | ||||||
|  |             self._redirect_to_https = bool(settings['RedirectToHTTPS']) | ||||||
|  |         except Exception as e: | ||||||
|  |             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||||
|  |             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||||
							
								
								
									
										48
									
								
								kdb-bot/src/bot_api/configuration/authentication_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								kdb-bot/src/bot_api/configuration/authentication_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | import traceback | ||||||
|  | from datetime import datetime | ||||||
|  |  | ||||||
|  | from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthenticationSettings(ConfigurationModelABC): | ||||||
|  |  | ||||||
|  |     def __init__(self): | ||||||
|  |         ConfigurationModelABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._secret_key = '' | ||||||
|  |         self._issuer = '' | ||||||
|  |         self._audience = '' | ||||||
|  |         self._token_expire_time = 0 | ||||||
|  |         self._refresh_token_expire_time = 0 | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def secret_key(self) -> str: | ||||||
|  |         return self._secret_key | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def issuer(self) -> str: | ||||||
|  |         return self._issuer | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def audience(self) -> str: | ||||||
|  |         return self._audience | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def token_expire_time(self) -> int: | ||||||
|  |         return self._token_expire_time | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def refresh_token_expire_time(self) -> int: | ||||||
|  |         return self._refresh_token_expire_time | ||||||
|  |  | ||||||
|  |     def from_dict(self, settings: dict): | ||||||
|  |         try: | ||||||
|  |             self._secret_key = settings['SecretKey'] | ||||||
|  |             self._issuer = settings['Issuer'] | ||||||
|  |             self._audience = settings['Audience'] | ||||||
|  |             self._token_expire_time = int(settings['TokenExpireTime']) | ||||||
|  |             self._refresh_token_expire_time = int(settings['RefreshTokenExpireTime']) | ||||||
|  |         except Exception as e: | ||||||
|  |             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||||
|  |             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||||
|  | from cpl_core.console import Console | ||||||
|  | from cpl_query.extension import List | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DiscordAuthenticationSettings(ConfigurationModelABC): | ||||||
|  |  | ||||||
|  |     def __init__(self): | ||||||
|  |         ConfigurationModelABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._client_secret = '' | ||||||
|  |         self._redirect_url = '' | ||||||
|  |         self._scope = List() | ||||||
|  |         self._token_url = '' | ||||||
|  |         self._auth_url = '' | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def client_secret(self) -> str: | ||||||
|  |         return self._client_secret | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def redirect_url(self) -> str: | ||||||
|  |         return self._redirect_url | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def scope(self) -> List[str]: | ||||||
|  |         return self._scope | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def token_url(self) -> str: | ||||||
|  |         return self._token_url | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def auth_url(self) -> str: | ||||||
|  |         return self._auth_url | ||||||
|  |  | ||||||
|  |     def from_dict(self, settings: dict): | ||||||
|  |         try: | ||||||
|  |             self._client_secret = settings['ClientSecret'] | ||||||
|  |             self._redirect_url = settings['RedirectURL'] | ||||||
|  |             self._scope = List(str, settings['Scope']) | ||||||
|  |             self._token_url = settings['TokenURL'] | ||||||
|  |             self._auth_url = settings['AuthURL'] | ||||||
|  |         except Exception as e: | ||||||
|  |             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||||
|  |             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||||
							
								
								
									
										23
									
								
								kdb-bot/src/bot_api/configuration/frontend_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								kdb-bot/src/bot_api/configuration/frontend_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class FrontendSettings(ConfigurationModelABC): | ||||||
|  |  | ||||||
|  |     def __init__(self): | ||||||
|  |         ConfigurationModelABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._url = '' | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def url(self) -> str: | ||||||
|  |         return self._url | ||||||
|  |  | ||||||
|  |     def from_dict(self, settings: dict): | ||||||
|  |         try: | ||||||
|  |             self._url = settings['URL'] | ||||||
|  |         except Exception as e: | ||||||
|  |             Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings') | ||||||
|  |             Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') | ||||||
							
								
								
									
										55
									
								
								kdb-bot/src/bot_api/configuration/version_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								kdb-bot/src/bot_api/configuration/version_settings.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC | ||||||
|  | from cpl_cli.configuration.version_settings_name_enum import VersionSettingsNameEnum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class VersionSettings(ConfigurationModelABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             major: str = None, | ||||||
|  |             minor: str = None, | ||||||
|  |             micro: str = None | ||||||
|  |     ): | ||||||
|  |         ConfigurationModelABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._major: Optional[str] = major | ||||||
|  |         self._minor: Optional[str] = minor | ||||||
|  |         self._micro: Optional[str] = micro | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def major(self) -> str: | ||||||
|  |         return self._major | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def minor(self) -> str: | ||||||
|  |         return self._minor | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def micro(self) -> str: | ||||||
|  |         return self._micro | ||||||
|  |  | ||||||
|  |     def to_str(self) -> str: | ||||||
|  |         if self._micro is None: | ||||||
|  |             return f'{self._major}.{self._minor}' | ||||||
|  |         else: | ||||||
|  |             return f'{self._major}.{self._minor}.{self._micro}' | ||||||
|  |  | ||||||
|  |     def from_dict(self, settings: dict): | ||||||
|  |         self._major = settings[VersionSettingsNameEnum.major.value] | ||||||
|  |         self._minor = settings[VersionSettingsNameEnum.minor.value] | ||||||
|  |         micro = settings[VersionSettingsNameEnum.micro.value] | ||||||
|  |         if micro != '': | ||||||
|  |             self._micro = micro | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         version = { | ||||||
|  |             VersionSettingsNameEnum.major.value: self._major, | ||||||
|  |             VersionSettingsNameEnum.minor.value: self._minor, | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if self._micro is not None: | ||||||
|  |             version[VersionSettingsNameEnum.micro.value] = self._micro | ||||||
|  |  | ||||||
|  |         return version | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/controller/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/controller/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.controller' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										155
									
								
								kdb-bot/src/bot_api/controller/auth_controller.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								kdb-bot/src/bot_api/controller/auth_controller.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | |||||||
|  | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
|  | from cpl_core.mailing import EMailClientABC, EMailClientSettings | ||||||
|  | from cpl_translation import TranslatePipe | ||||||
|  | from flask import request, jsonify, Response | ||||||
|  |  | ||||||
|  | from bot_api.abc.auth_service_abc import AuthServiceABC | ||||||
|  | from bot_api.api import Api | ||||||
|  | from bot_api.exception.service_error_code_enum import ServiceErrorCode | ||||||
|  | from bot_api.exception.service_exception import ServiceException | ||||||
|  | from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria | ||||||
|  | from bot_api.json_processor import JSONProcessor | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
|  | from bot_api.model.auth_user_dto import AuthUserDTO | ||||||
|  | from bot_api.model.reset_password_dto import ResetPasswordDTO | ||||||
|  | from bot_api.model.token_dto import TokenDTO | ||||||
|  | from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO | ||||||
|  | from bot_api.route.route import Route | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthController: | ||||||
|  |     BasePath = '/api/auth' | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             config: ConfigurationABC, | ||||||
|  |             env: ApplicationEnvironmentABC, | ||||||
|  |             logger: ApiLogger, | ||||||
|  |             t: TranslatePipe, | ||||||
|  |             api: Api, | ||||||
|  |             mail_settings: EMailClientSettings, | ||||||
|  |             mailer: EMailClientABC, | ||||||
|  |             auth_service: AuthServiceABC | ||||||
|  |     ): | ||||||
|  |         self._config = config | ||||||
|  |         self._env = env | ||||||
|  |         self._logger = logger | ||||||
|  |         self._t = t | ||||||
|  |         self._api = api | ||||||
|  |         self._mail_settings = mail_settings | ||||||
|  |         self._mailer = mailer | ||||||
|  |         self._auth_service = auth_service | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/users') | ||||||
|  |     @Route.authorize(role=AuthRoleEnum.admin) | ||||||
|  |     async def get_all_users(self) -> Response: | ||||||
|  |         result = await self._auth_service.get_all_auth_users_async() | ||||||
|  |         return jsonify(result.select(lambda x: x.to_dict())) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/users/get/filtered') | ||||||
|  |     @Route.authorize(role=AuthRoleEnum.admin) | ||||||
|  |     async def get_filtered_users(self) -> Response: | ||||||
|  |         dto: AuthUserSelectCriteria = JSONProcessor.process(AuthUserSelectCriteria, request.get_json(force=True, silent=True)) | ||||||
|  |         result = await self._auth_service.get_filtered_auth_users_async(dto) | ||||||
|  |         result.result = result.result.select(lambda x: x.to_dict()) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/users/get/<email>') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def get_user_from_email(self, email: str) -> Response: | ||||||
|  |         result = await self._auth_service.get_auth_user_by_email_async(email) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/users/find/<email>') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def find_user_from_email(self, email: str) -> Response: | ||||||
|  |         result = await self._auth_service.find_auth_user_by_email_async(email) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/register') | ||||||
|  |     async def register(self): | ||||||
|  |         dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         await self._auth_service.add_auth_user_async(dto) | ||||||
|  |         return '', 200 | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/register-by-id/<id>') | ||||||
|  |     async def register_id(self, id: str): | ||||||
|  |         result = await self._auth_service.confirm_email_async(id) | ||||||
|  |         return jsonify(result) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/login') | ||||||
|  |     async def login(self) -> Response: | ||||||
|  |         dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         result = await self._auth_service.login_async(dto) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/verify-login') | ||||||
|  |     async def verify_login(self): | ||||||
|  |         token = None | ||||||
|  |         result = False | ||||||
|  |         if 'Authorization' in request.headers: | ||||||
|  |             bearer = request.headers.get('Authorization') | ||||||
|  |             token = bearer.split()[1] | ||||||
|  |  | ||||||
|  |         if token is not None: | ||||||
|  |             result = self._auth_service.verify_login(token) | ||||||
|  |  | ||||||
|  |         return jsonify(result) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/forgot-password/<email>') | ||||||
|  |     async def forgot_password(self, email: str): | ||||||
|  |         await self._auth_service.forgot_password_async(email) | ||||||
|  |         return '', 200 | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/confirm-forgot-password/<id>') | ||||||
|  |     async def confirm_forgot_password(self, id: str): | ||||||
|  |         result = await self._auth_service.confirm_forgot_password_async(id) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/reset-password') | ||||||
|  |     async def reset_password(self): | ||||||
|  |         dto: ResetPasswordDTO = JSONProcessor.process(ResetPasswordDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         await self._auth_service.reset_password_async(dto) | ||||||
|  |         return '', 200 | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/update-user') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def update_user(self): | ||||||
|  |         dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         await self._auth_service.update_user_async(dto) | ||||||
|  |         return '', 200 | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/update-user-as-admin') | ||||||
|  |     @Route.authorize(role=AuthRoleEnum.admin) | ||||||
|  |     async def update_user_as_admin(self): | ||||||
|  |         dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         await self._auth_service.update_user_as_admin_async(dto) | ||||||
|  |         return '', 200 | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/refresh') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def refresh(self) -> Response: | ||||||
|  |         dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         result = await self._auth_service.refresh_async(dto) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/revoke') | ||||||
|  |     async def revoke(self): | ||||||
|  |         dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         await self._auth_service.revoke_async(dto) | ||||||
|  |         return '', 200 | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/delete-user') | ||||||
|  |     @Route.authorize(role=AuthRoleEnum.admin) | ||||||
|  |     async def delete_user(self): | ||||||
|  |         dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         await self._auth_service.delete_auth_user_async(dto) | ||||||
|  |         return '', 200 | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/delete-user-by-mail/<email>') | ||||||
|  |     @Route.authorize(role=AuthRoleEnum.admin) | ||||||
|  |     async def delete_user_by_mail(self, email: str): | ||||||
|  |         await self._auth_service.delete_auth_user_by_email_async(email) | ||||||
|  |         return '', 200 | ||||||
							
								
								
									
										89
									
								
								kdb-bot/src/bot_api/controller/auth_discord_controller.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								kdb-bot/src/bot_api/controller/auth_discord_controller.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | import os | ||||||
|  | import uuid | ||||||
|  |  | ||||||
|  | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
|  | from cpl_core.mailing import EMailClientABC, EMailClientSettings | ||||||
|  | from cpl_core.utils import CredentialManager | ||||||
|  | from cpl_discord.service import DiscordBotServiceABC | ||||||
|  | from cpl_translation import TranslatePipe | ||||||
|  | from flask import jsonify, Response | ||||||
|  | from flask import request, session | ||||||
|  | from requests_oauthlib import OAuth2Session | ||||||
|  |  | ||||||
|  | from bot_api.abc.auth_service_abc import AuthServiceABC | ||||||
|  | from bot_api.api import Api | ||||||
|  | from bot_api.configuration.discord_authentication_settings import DiscordAuthenticationSettings | ||||||
|  | from bot_api.json_processor import JSONProcessor | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
|  | from bot_api.model.auth_user_dto import AuthUserDTO | ||||||
|  | from bot_api.model.o_auth_dto import OAuthDTO | ||||||
|  | from bot_api.route.route import Route | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  |  | ||||||
|  | # Disable SSL requirement | ||||||
|  | os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthDiscordController: | ||||||
|  |     BasePath = '/api/auth/discord' | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             auth_settings: DiscordAuthenticationSettings, | ||||||
|  |             config: ConfigurationABC, | ||||||
|  |             env: ApplicationEnvironmentABC, | ||||||
|  |             logger: ApiLogger, | ||||||
|  |             bot: DiscordBotServiceABC, | ||||||
|  |             t: TranslatePipe, | ||||||
|  |             api: Api, | ||||||
|  |             mail_settings: EMailClientSettings, | ||||||
|  |             mailer: EMailClientABC, | ||||||
|  |             auth_service: AuthServiceABC | ||||||
|  |     ): | ||||||
|  |         self._auth_settings = auth_settings | ||||||
|  |         self._config = config | ||||||
|  |         self._env = env | ||||||
|  |         self._logger = logger | ||||||
|  |         self._bot = bot | ||||||
|  |         self._t = t | ||||||
|  |         self._api = api | ||||||
|  |         self._mail_settings = mail_settings | ||||||
|  |         self._mailer = mailer | ||||||
|  |         self._auth_service = auth_service | ||||||
|  |  | ||||||
|  |     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) | ||||||
|  |         token = discord.fetch_token( | ||||||
|  |             self._auth_settings.token_url, | ||||||
|  |             client_secret=CredentialManager.decrypt(self._auth_settings.client_secret), | ||||||
|  |             authorization_response=request.url, | ||||||
|  |         ) | ||||||
|  |         discord = OAuth2Session(self._bot.user.id, token=token) | ||||||
|  |         return discord.get('https://discordapp.com/api' + '/users/@me').json() | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/get-url') | ||||||
|  |     async def get_url(self): | ||||||
|  |         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) | ||||||
|  |         return jsonify({'loginUrl': login_url}) | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/create-user') | ||||||
|  |     async def discord_create_user(self) -> Response: | ||||||
|  |         response = self._get_user_from_discord_response() | ||||||
|  |         result = await self._auth_service.add_auth_user_by_discord_async(AuthUserDTO( | ||||||
|  |             0, | ||||||
|  |             response['username'], | ||||||
|  |             response['discriminator'], | ||||||
|  |             response['email'], | ||||||
|  |             str(uuid.uuid4()), | ||||||
|  |             None, | ||||||
|  |             AuthRoleEnum.normal | ||||||
|  |         ), response['id']) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/register') | ||||||
|  |     async def discord_register(self): | ||||||
|  |         dto: OAuthDTO = JSONProcessor.process(OAuthDTO, request.get_json(force=True, silent=True)) | ||||||
|  |         await self._auth_service.add_auth_user_by_oauth_async(dto) | ||||||
|  |         return '', 200 | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/controller/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/controller/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.controller.discord' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										65
									
								
								kdb-bot/src/bot_api/controller/discord/server_controller.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								kdb-bot/src/bot_api/controller/discord/server_controller.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
|  | from cpl_core.mailing import EMailClientABC, EMailClientSettings | ||||||
|  | from cpl_translation import TranslatePipe | ||||||
|  | from flask import Response, jsonify, request | ||||||
|  |  | ||||||
|  | from bot_api.api import Api | ||||||
|  | from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria | ||||||
|  | from bot_api.json_processor import JSONProcessor | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
|  | from bot_api.route.route import Route | ||||||
|  | from bot_api.service.discord_service import DiscordService | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ServerController: | ||||||
|  |     BasePath = f'/api/discord/server' | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             config: ConfigurationABC, | ||||||
|  |             env: ApplicationEnvironmentABC, | ||||||
|  |             logger: ApiLogger, | ||||||
|  |             t: TranslatePipe, | ||||||
|  |             api: Api, | ||||||
|  |             mail_settings: EMailClientSettings, | ||||||
|  |             mailer: EMailClientABC, | ||||||
|  |             discord_service: DiscordService | ||||||
|  |     ): | ||||||
|  |         self._config = config | ||||||
|  |         self._env = env | ||||||
|  |         self._logger = logger | ||||||
|  |         self._t = t | ||||||
|  |         self._api = api | ||||||
|  |         self._mail_settings = mail_settings | ||||||
|  |         self._mailer = mailer | ||||||
|  |         self._discord_service = discord_service | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/get/servers') | ||||||
|  |     @Route.authorize(role=AuthRoleEnum.admin) | ||||||
|  |     async def get_all_servers(self) -> Response: | ||||||
|  |         result = await self._discord_service.get_all_servers() | ||||||
|  |         result = result.select(lambda x: x.to_dict()) | ||||||
|  |         return jsonify(result) | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/get/servers-by-user') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def get_all_servers_by_user(self) -> Response: | ||||||
|  |         result = await self._discord_service.get_all_servers_by_user() | ||||||
|  |         result = result.select(lambda x: x.to_dict()) | ||||||
|  |         return jsonify(result) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/get/filtered') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def get_filtered_servers(self) -> Response: | ||||||
|  |         dto: ServerSelectCriteria = JSONProcessor.process(ServerSelectCriteria, request.get_json(force=True, silent=True)) | ||||||
|  |         result = await self._discord_service.get_filtered_servers_async(dto) | ||||||
|  |         result.result = result.result.select(lambda x: x.to_dict()) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/get/<id>') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def get_server_by_id(self, id: int) -> Response: | ||||||
|  |         result = await self._discord_service.get_server_by_id_async(id) | ||||||
|  |         return jsonify(result.to_dict()) | ||||||
							
								
								
									
										78
									
								
								kdb-bot/src/bot_api/controller/gui_controller.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								kdb-bot/src/bot_api/controller/gui_controller.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | import os | ||||||
|  |  | ||||||
|  | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
|  | from cpl_core.mailing import EMail, EMailClientABC, EMailClientSettings | ||||||
|  | from cpl_translation import TranslatePipe | ||||||
|  | from flask import jsonify | ||||||
|  |  | ||||||
|  | from bot_api.api import Api | ||||||
|  | from bot_api.configuration.authentication_settings import AuthenticationSettings | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
|  | from bot_api.model.settings_dto import SettingsDTO | ||||||
|  | from bot_api.model.version_dto import VersionDTO | ||||||
|  | from bot_api.route.route import Route | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class GuiController: | ||||||
|  |     BasePath = f'/api/gui' | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             config: ConfigurationABC, | ||||||
|  |             env: ApplicationEnvironmentABC, | ||||||
|  |             logger: ApiLogger, | ||||||
|  |             t: TranslatePipe, | ||||||
|  |             api: Api, | ||||||
|  |             mail_settings: EMailClientSettings, | ||||||
|  |             mailer: EMailClientABC, | ||||||
|  |             auth_settings: AuthenticationSettings | ||||||
|  |     ): | ||||||
|  |         self._config = config | ||||||
|  |         self._env = env | ||||||
|  |         self._logger = logger | ||||||
|  |         self._t = t | ||||||
|  |         self._api = api | ||||||
|  |         self._mail_settings = mail_settings | ||||||
|  |         self._mailer = mailer | ||||||
|  |         self._auth_settings = auth_settings | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/api-version') | ||||||
|  |     async def api_version(self): | ||||||
|  |         import bot_api | ||||||
|  |         version = bot_api.version_info | ||||||
|  |         return VersionDTO(version.major, version.minor, version.micro).to_dict() | ||||||
|  |  | ||||||
|  |     @Route.get(f'{BasePath}/settings') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def settings(self): | ||||||
|  |         import bot_api | ||||||
|  |         version = bot_api.version_info | ||||||
|  |  | ||||||
|  |         return jsonify(SettingsDTO( | ||||||
|  |             '', | ||||||
|  |             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._mail_settings.user_name, | ||||||
|  |             self._mail_settings.port, | ||||||
|  |             self._mail_settings.host, | ||||||
|  |             self._mail_settings.user_name, | ||||||
|  |             self._mail_settings.user_name, | ||||||
|  |         ).to_dict()) | ||||||
|  |  | ||||||
|  |     @Route.post(f'{BasePath}/send-test-mail/<email>') | ||||||
|  |     @Route.authorize | ||||||
|  |     async def send_test_mail(self, email: str): | ||||||
|  |         mail = EMail() | ||||||
|  |         mail.add_header('Mime-Version: 1.0') | ||||||
|  |         mail.add_header('Content-Type: text/plain; charset=utf-8') | ||||||
|  |         mail.add_header('Content-Transfer-Encoding: quoted-printable') | ||||||
|  |         mail.add_receiver(email) | ||||||
|  |         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) | ||||||
|  |         self._mailer.send_mail(mail) | ||||||
|  |         return '', 200 | ||||||
| @@ -11,11 +11,11 @@ Discord bot  for the Keksdose discord Server | |||||||
| 
 | 
 | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| __title__ = 'bot_core.abc' | __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 sh-edraft.de' | ||||||
| __version__ = '0.2.3' | __version__ = '0.3.dev25' | ||||||
| 
 | 
 | ||||||
| from collections import namedtuple | from collections import namedtuple | ||||||
| 
 | 
 | ||||||
| @@ -23,4 +23,4 @@ from collections import namedtuple | |||||||
| # imports: | # imports: | ||||||
| 
 | 
 | ||||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
| version_info = VersionInfo(major='0', minor='2', micro='3') | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										13
									
								
								kdb-bot/src/bot_api/event/bot_api_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								kdb-bot/src/bot_api/event/bot_api_on_ready_event.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | from cpl_discord.events import OnReadyABC | ||||||
|  |  | ||||||
|  | from bot_api.api_thread import ApiThread | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BotApiOnReadyEvent(OnReadyABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, api: ApiThread): | ||||||
|  |         OnReadyABC.__init__(self) | ||||||
|  |         self._api = api | ||||||
|  |  | ||||||
|  |     async def on_ready(self): | ||||||
|  |         self._api.start() | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/exception/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/exception/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.exception' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										24
									
								
								kdb-bot/src/bot_api/exception/service_error_code_enum.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								kdb-bot/src/bot_api/exception/service_error_code_enum.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | from enum import Enum | ||||||
|  |  | ||||||
|  | from werkzeug.exceptions import Unauthorized | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ServiceErrorCode(Enum): | ||||||
|  |  | ||||||
|  |     Unknown = 0 | ||||||
|  |  | ||||||
|  |     InvalidDependencies = 1 | ||||||
|  |     InvalidData = 2 | ||||||
|  |     NotFound = 3 | ||||||
|  |     DataAlreadyExists = 4 | ||||||
|  |     UnableToAdd = 5 | ||||||
|  |     UnableToDelete = 6 | ||||||
|  |  | ||||||
|  |     InvalidUser = 7 | ||||||
|  |  | ||||||
|  |     ConnectionFailed = 8 | ||||||
|  |     Timeout = 9 | ||||||
|  |     MailError = 10 | ||||||
|  |  | ||||||
|  |     Unauthorized = 11 | ||||||
|  |     Forbidden = 12 | ||||||
							
								
								
									
										13
									
								
								kdb-bot/src/bot_api/exception/service_exception.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								kdb-bot/src/bot_api/exception/service_exception.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | from bot_api.exception.service_error_code_enum import ServiceErrorCode | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ServiceException(Exception): | ||||||
|  |  | ||||||
|  |     def __init__(self, error_code: ServiceErrorCode, message: str, *args): | ||||||
|  |         Exception.__init__(self, *args) | ||||||
|  |  | ||||||
|  |         self.error_code = error_code | ||||||
|  |         self.message = message | ||||||
|  |  | ||||||
|  |     def get_detailed_message(self) -> str: | ||||||
|  |         return f'ServiceException - ErrorCode: {self.error_code} - ErrorMessage: {self.message}' | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/filter/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/filter/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.filter' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										23
									
								
								kdb-bot/src/bot_api/filter/auth_user_select_criteria.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								kdb-bot/src/bot_api/filter/auth_user_select_criteria.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | from bot_api.abc.select_criteria_abc import SelectCriteriaABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthUserSelectCriteria(SelectCriteriaABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             page_index: int, | ||||||
|  |             page_size: int, | ||||||
|  |             sort_direction: str, | ||||||
|  |             sort_column: str, | ||||||
|  |  | ||||||
|  |             first_name: str, | ||||||
|  |             last_name: str, | ||||||
|  |             email: str, | ||||||
|  |             auth_role: int | ||||||
|  |     ): | ||||||
|  |         SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column) | ||||||
|  |  | ||||||
|  |         self.first_name = first_name | ||||||
|  |         self.last_name = last_name | ||||||
|  |         self.email = email | ||||||
|  |         self.auth_role = auth_role | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/filter/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/filter/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.filter.discord' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										17
									
								
								kdb-bot/src/bot_api/filter/discord/server_select_criteria.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								kdb-bot/src/bot_api/filter/discord/server_select_criteria.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | from bot_api.abc.select_criteria_abc import SelectCriteriaABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ServerSelectCriteria(SelectCriteriaABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             page_index: int, | ||||||
|  |             page_size: int, | ||||||
|  |             sort_direction: str, | ||||||
|  |             sort_column: str, | ||||||
|  |  | ||||||
|  |             name: str, | ||||||
|  |     ): | ||||||
|  |         SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column) | ||||||
|  |  | ||||||
|  |         self.name = name | ||||||
							
								
								
									
										39
									
								
								kdb-bot/src/bot_api/json_processor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								kdb-bot/src/bot_api/json_processor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | from inspect import signature, Parameter | ||||||
|  |  | ||||||
|  | from cpl_core.utils import String | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class JSONProcessor: | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def process(_t: type, values: dict) -> object: | ||||||
|  |         args = [] | ||||||
|  |  | ||||||
|  |         sig = signature(_t.__init__) | ||||||
|  |         for param in sig.parameters.items(): | ||||||
|  |             parameter = param[1] | ||||||
|  |             if parameter.name == 'self' or parameter.annotation == Parameter.empty: | ||||||
|  |                 continue | ||||||
|  |  | ||||||
|  |             name = String.convert_to_camel_case(parameter.name) | ||||||
|  |             name = name.replace('Dto', 'DTO') | ||||||
|  |             name_first_lower = String.first_to_lower(name) | ||||||
|  |             if name in values or name_first_lower in values: | ||||||
|  |                 value = '' | ||||||
|  |                 if name in values: | ||||||
|  |                     value = values[name] | ||||||
|  |                 else: | ||||||
|  |                     value = values[name_first_lower] | ||||||
|  |  | ||||||
|  |                 if isinstance(value, dict): | ||||||
|  |                     value = JSONProcessor.process(parameter.annotation, value) | ||||||
|  |  | ||||||
|  |                 args.append(value) | ||||||
|  |  | ||||||
|  |             elif parameter.default != Parameter.empty: | ||||||
|  |                 args.append(parameter.default) | ||||||
|  |  | ||||||
|  |             else: | ||||||
|  |                 args.append(None) | ||||||
|  |  | ||||||
|  |         return _t(*args) | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/logging/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/logging/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.logging' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										11
									
								
								kdb-bot/src/bot_api/logging/api_logger.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								kdb-bot/src/bot_api/logging/api_logger.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | from cpl_core.configuration import ConfigurationABC | ||||||
|  | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
|  | from cpl_core.time import TimeFormatSettings | ||||||
|  |  | ||||||
|  | from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ApiLogger(CustomFileLoggerABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, config: ConfigurationABC, time_format: TimeFormatSettings, env: ApplicationEnvironmentABC): | ||||||
|  |         CustomFileLoggerABC.__init__(self, 'Api', config, time_format, env) | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/model/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.model' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										99
									
								
								kdb-bot/src/bot_api/model/auth_user_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								kdb-bot/src/bot_api/model/auth_user_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthUserDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             id: int = None, | ||||||
|  |             first_name: str = None, | ||||||
|  |             last_name: str = None, | ||||||
|  |             email: str = None, | ||||||
|  |             password: str = None, | ||||||
|  |             confirmation_id: Optional[str] = None, | ||||||
|  |             auth_role: AuthRoleEnum = None, | ||||||
|  |     ): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._id = id | ||||||
|  |         self._first_name = first_name | ||||||
|  |         self._last_name = last_name | ||||||
|  |         self._email = email | ||||||
|  |         self._password = password | ||||||
|  |         self._is_confirmed = confirmation_id is None | ||||||
|  |         self._auth_role = auth_role | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def id(self) -> int: | ||||||
|  |         return self._id | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def first_name(self) -> str: | ||||||
|  |         return self._first_name | ||||||
|  |  | ||||||
|  |     @first_name.setter | ||||||
|  |     def first_name(self, value: str): | ||||||
|  |         self._first_name = value | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def last_name(self) -> str: | ||||||
|  |         return self._last_name | ||||||
|  |  | ||||||
|  |     @last_name.setter | ||||||
|  |     def last_name(self, value: str): | ||||||
|  |         self._last_name = value | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def email(self) -> str: | ||||||
|  |         return self._email | ||||||
|  |  | ||||||
|  |     @email.setter | ||||||
|  |     def email(self, value: str): | ||||||
|  |         self._email = value | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def password(self) -> str: | ||||||
|  |         return self._password | ||||||
|  |  | ||||||
|  |     @password.setter | ||||||
|  |     def password(self, value: str): | ||||||
|  |         self._password = value | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def is_confirmed(self) -> Optional[str]: | ||||||
|  |         return self._is_confirmed | ||||||
|  |  | ||||||
|  |     @is_confirmed.setter | ||||||
|  |     def is_confirmed(self, value: Optional[str]): | ||||||
|  |         self._is_confirmed = value | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def auth_role(self) -> AuthRoleEnum: | ||||||
|  |         return self._auth_role | ||||||
|  |  | ||||||
|  |     @auth_role.setter | ||||||
|  |     def auth_role(self, value: AuthRoleEnum): | ||||||
|  |         self._auth_role = value | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._id = values['id'] | ||||||
|  |         self._first_name = values['firstName'] | ||||||
|  |         self._last_name = values['lastName'] | ||||||
|  |         self._email = values['email'] | ||||||
|  |         self._password = values['password'] | ||||||
|  |         self._is_confirmed = values['isConfirmed'] | ||||||
|  |         self._auth_role = values['authRole'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'id': self._id, | ||||||
|  |             'firstName': self._first_name, | ||||||
|  |             'lastName': self._last_name, | ||||||
|  |             'email': self._email, | ||||||
|  |             'password': self._password, | ||||||
|  |             'isConfirmed': self._is_confirmed, | ||||||
|  |             'authRole': self._auth_role.value, | ||||||
|  |         } | ||||||
							
								
								
									
										21
									
								
								kdb-bot/src/bot_api/model/auth_user_filtered_result_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								kdb-bot/src/bot_api/model/auth_user_filtered_result_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | from cpl_query.extension import List | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  | from bot_data.filtered_result import FilteredResult | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthUserFilteredResultDTO(DtoABC, FilteredResult): | ||||||
|  |  | ||||||
|  |     def __init__(self, result: List = None, total_count: int = 0): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |         FilteredResult.__init__(self, result, total_count) | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._result = values['users'] | ||||||
|  |         self._total_count = values['totalCount'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'users': self.result, | ||||||
|  |             'totalCount': self.total_count | ||||||
|  |         } | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/model/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/model/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.model.discord' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										58
									
								
								kdb-bot/src/bot_api/model/discord/server_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								kdb-bot/src/bot_api/model/discord/server_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ServerDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             server_id: int, | ||||||
|  |             discord_id: int, | ||||||
|  |             name: str, | ||||||
|  |             member_count: int, | ||||||
|  |             icon_url: Optional[str] | ||||||
|  |  | ||||||
|  |     ): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._server_id = server_id | ||||||
|  |         self._discord_id = discord_id | ||||||
|  |         self._name = name | ||||||
|  |         self._member_count = member_count | ||||||
|  |         self._icon_url = icon_url | ||||||
|  |          | ||||||
|  |     @property | ||||||
|  |     def server_id(self) -> int: | ||||||
|  |         return self._server_id | ||||||
|  |      | ||||||
|  |     @property | ||||||
|  |     def discord_id(self) -> int: | ||||||
|  |         return self._discord_id | ||||||
|  |      | ||||||
|  |     @property | ||||||
|  |     def name(self) -> str: | ||||||
|  |         return self._name | ||||||
|  |      | ||||||
|  |     @property | ||||||
|  |     def member_count(self) -> int: | ||||||
|  |         return self._member_count | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def icon_url(self) -> Optional[str]: | ||||||
|  |         return self._icon_url | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._server_id = int(values['serverId']) | ||||||
|  |         self._discord_id = int(values['discordId']) | ||||||
|  |         self._name = values['name'] | ||||||
|  |         self._icon_url = values['iconURL'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'serverId': self._server_id, | ||||||
|  |             'discordId': self._discord_id, | ||||||
|  |             'name': self._name, | ||||||
|  |             'memberCount': self._member_count, | ||||||
|  |             'iconURL': self._icon_url, | ||||||
|  |         } | ||||||
| @@ -0,0 +1,21 @@ | |||||||
|  | from cpl_query.extension import List | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  | from bot_data.filtered_result import FilteredResult | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ServerFilteredResultDTO(DtoABC, FilteredResult): | ||||||
|  |  | ||||||
|  |     def __init__(self, result: List = None, total_count: int = 0): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |         FilteredResult.__init__(self, result, total_count) | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._result = values['servers'] | ||||||
|  |         self._total_count = values['totalCount'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'servers': self.result, | ||||||
|  |             'totalCount': self.total_count | ||||||
|  |         } | ||||||
							
								
								
									
										21
									
								
								kdb-bot/src/bot_api/model/email_string_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								kdb-bot/src/bot_api/model/email_string_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class EMailStringDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, email: str): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._email = email | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._email = values['email'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'email': self._email | ||||||
|  |         } | ||||||
							
								
								
									
										34
									
								
								kdb-bot/src/bot_api/model/error_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								kdb-bot/src/bot_api/model/error_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | import traceback | ||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  | from bot_api.exception.service_error_code_enum import ServiceErrorCode | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ErrorDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, error_code: Optional[ServiceErrorCode], message: str): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._error_code = ServiceErrorCode.Unknown if error_code is None else error_code | ||||||
|  |         self._message = message | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def error_code(self) -> ServiceErrorCode: | ||||||
|  |         return self._error_code | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def message(self) -> str: | ||||||
|  |         return self._message | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._error_code = values['ErrorCode'] | ||||||
|  |         self._message = values['Message'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'errorCode': int(self._error_code.value), | ||||||
|  |             'message': self._message | ||||||
|  |         } | ||||||
							
								
								
									
										44
									
								
								kdb-bot/src/bot_api/model/o_auth_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								kdb-bot/src/bot_api/model/o_auth_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  | from bot_api.model.auth_user_dto import AuthUserDTO | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class OAuthDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             user: AuthUserDTO, | ||||||
|  |             o_auth_id: Optional[str], | ||||||
|  |     ): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._user = user | ||||||
|  |         self._oauth_id = o_auth_id | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def user(self) -> AuthUserDTO: | ||||||
|  |         return self._user | ||||||
|  |  | ||||||
|  |     @user.setter | ||||||
|  |     def user(self, value: AuthUserDTO): | ||||||
|  |         self._user = value | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def oauth_id(self) -> Optional[str]: | ||||||
|  |         return self._oauth_id | ||||||
|  |  | ||||||
|  |     @oauth_id.setter | ||||||
|  |     def oauth_id(self, value: Optional[str]): | ||||||
|  |         self._oauth_id = value | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._user = AuthUserDTO().from_dict(values['user']) | ||||||
|  |         self._oauth_id = values['oAuthId'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'user': self._user.to_dict(), | ||||||
|  |             'oAuthId': self._oauth_id | ||||||
|  |         } | ||||||
							
								
								
									
										32
									
								
								kdb-bot/src/bot_api/model/reset_password_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								kdb-bot/src/bot_api/model/reset_password_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ResetPasswordDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, id: str, password: str): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._id = id | ||||||
|  |         self._password = password | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def id(self) -> str: | ||||||
|  |         return self._id | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def password(self) -> str: | ||||||
|  |         return self._password | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._id = values['id'] | ||||||
|  |         self._password = values['password'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'id': self._id, | ||||||
|  |             'password': self._password | ||||||
|  |         } | ||||||
							
								
								
									
										67
									
								
								kdb-bot/src/bot_api/model/settings_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								kdb-bot/src/bot_api/model/settings_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | |||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  | from bot_api.model.version_dto import VersionDTO | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SettingsDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             web_version: str, | ||||||
|  |             api_version: VersionDTO, | ||||||
|  |             config_path: str, | ||||||
|  |             web_base_url: str, | ||||||
|  |             api_base_url: str, | ||||||
|  |             token_expire_time: int, | ||||||
|  |             refresh_token_expire_time: int, | ||||||
|  |             mail_user: str, | ||||||
|  |             mail_port: int, | ||||||
|  |             mail_host: str, | ||||||
|  |             mail_transceiver: str, | ||||||
|  |             mail_transceiver_address: str, | ||||||
|  |     ): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._web_version = web_version | ||||||
|  |         self._api_version = api_version | ||||||
|  |         self._config_path = config_path | ||||||
|  |         self._web_base_url = web_base_url | ||||||
|  |         self._api_base_url = api_base_url | ||||||
|  |  | ||||||
|  |         self._token_expire_time = token_expire_time | ||||||
|  |         self._refresh_token_expire_time = refresh_token_expire_time | ||||||
|  |  | ||||||
|  |         self._mail_user = mail_user | ||||||
|  |         self._mail_port = mail_port | ||||||
|  |         self._mail_host = mail_host | ||||||
|  |         self._mail_transceiver = mail_transceiver | ||||||
|  |         self._mail_transceiver_address = mail_transceiver_address | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._web_version = values['webVersion'] | ||||||
|  |         self._api_version.from_dict(values['apiVersion']) | ||||||
|  |         self._config_path = values['configPath'] | ||||||
|  |         self._web_base_url = values['webBaseURL'] | ||||||
|  |         self._api_base_url = values['apiBaseURL'] | ||||||
|  |         self._token_expire_time = values['tokenExpireTime'] | ||||||
|  |         self._refresh_token_expire_time = values['refreshTokenExpireTime'] | ||||||
|  |         self._mail_user = values['mailUser'] | ||||||
|  |         self._mail_port = values['mailPort'] | ||||||
|  |         self._mail_host = values['mailHost'] | ||||||
|  |         self._mail_transceiver = values['mailTransceiver'] | ||||||
|  |         self._mail_transceiver_address = values['mailTransceiverAddress'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'webVersion': self._web_version, | ||||||
|  |             'apiVersion': self._api_version.str, | ||||||
|  |             'configPath': self._config_path, | ||||||
|  |             'webBaseURL': self._web_base_url, | ||||||
|  |             'apiBaseURL': self._api_base_url, | ||||||
|  |             'tokenExpireTime': self._token_expire_time, | ||||||
|  |             'refreshTokenExpireTime': self._refresh_token_expire_time, | ||||||
|  |             'mailUser': self._mail_user, | ||||||
|  |             'mailPort': self._mail_port, | ||||||
|  |             'mailHost': self._mail_host, | ||||||
|  |             'mailTransceiver': self._mail_transceiver, | ||||||
|  |             'mailTransceiverAddress': self._mail_transceiver_address, | ||||||
|  |         } | ||||||
							
								
								
									
										32
									
								
								kdb-bot/src/bot_api/model/token_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								kdb-bot/src/bot_api/model/token_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TokenDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, token: str, refresh_token: str): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._token = token | ||||||
|  |         self._refresh_token = refresh_token | ||||||
|  |          | ||||||
|  |     @property | ||||||
|  |     def token(self) -> str: | ||||||
|  |         return self._token | ||||||
|  |      | ||||||
|  |     @property | ||||||
|  |     def refresh_token(self) -> str: | ||||||
|  |         return self._refresh_token | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._token = values['token'] | ||||||
|  |         self._refresh_token = values['refreshToken'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'token': self._token, | ||||||
|  |             'refreshToken': self._refresh_token | ||||||
|  |         } | ||||||
							
								
								
									
										45
									
								
								kdb-bot/src/bot_api/model/update_auth_user_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								kdb-bot/src/bot_api/model/update_auth_user_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  | from bot_api.model.auth_user_dto import AuthUserDTO | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class UpdateAuthUserDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             auth_user_dto: AuthUserDTO, | ||||||
|  |             new_auth_user_dto: AuthUserDTO, | ||||||
|  |             change_password: bool = False | ||||||
|  |     ): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._auth_user = auth_user_dto | ||||||
|  |         self._new_auth_user = new_auth_user_dto | ||||||
|  |         self._change_password = change_password | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def auth_user(self) -> AuthUserDTO: | ||||||
|  |         return self._auth_user | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def new_auth_user(self) -> AuthUserDTO: | ||||||
|  |         return self._new_auth_user | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def change_password(self) -> bool: | ||||||
|  |         return self._change_password | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._auth_user = values['authUser'] | ||||||
|  |         self._new_auth_user = values['newAuthUser'] | ||||||
|  |         self._change_password = False if 'changePassword' not in values else bool(values['changePassword']) | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'authUser': self._auth_user, | ||||||
|  |             'newAuthUser': self._new_auth_user, | ||||||
|  |             'changePassword': self._change_password | ||||||
|  |         } | ||||||
							
								
								
									
										43
									
								
								kdb-bot/src/bot_api/model/version_dto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								kdb-bot/src/bot_api/model/version_dto.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | import traceback | ||||||
|  |  | ||||||
|  | from cpl_core.console import Console | ||||||
|  |  | ||||||
|  | from bot_api.abc.dto_abc import DtoABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class VersionDTO(DtoABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, major: str = None, minor: str = None, micro: str = None): | ||||||
|  |         DtoABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._major = major | ||||||
|  |         self._minor = minor | ||||||
|  |         self._micro = micro | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def major(self) -> str: | ||||||
|  |         return self._major | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def minor(self) -> str: | ||||||
|  |         return self._minor | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def micro(self) -> str: | ||||||
|  |         return self._micro | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def str(self) -> str: | ||||||
|  |         return f'{self._major}.{self._minor}.{self._micro}' | ||||||
|  |  | ||||||
|  |     def from_dict(self, values: dict): | ||||||
|  |         self._major = values['major'] | ||||||
|  |         self._minor = values['minor'] | ||||||
|  |         self._micro = values['micro'] | ||||||
|  |  | ||||||
|  |     def to_dict(self) -> dict: | ||||||
|  |         return { | ||||||
|  |             'major': self._major, | ||||||
|  |             'minor': self._minor, | ||||||
|  |             'micro': self._micro, | ||||||
|  |         } | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/route/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/route/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.route' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										103
									
								
								kdb-bot/src/bot_api/route/route.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								kdb-bot/src/bot_api/route/route.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | |||||||
|  | import functools | ||||||
|  | from functools import wraps | ||||||
|  | from typing import Optional, Callable | ||||||
|  |  | ||||||
|  | from flask import request, jsonify | ||||||
|  | from flask_cors import cross_origin | ||||||
|  |  | ||||||
|  | from bot_api.abc.auth_service_abc import AuthServiceABC | ||||||
|  | from bot_api.exception.service_error_code_enum import ServiceErrorCode | ||||||
|  | from bot_api.exception.service_exception import ServiceException | ||||||
|  | from bot_api.model.error_dto import ErrorDTO | ||||||
|  | from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Route: | ||||||
|  |     registered_routes = {} | ||||||
|  |  | ||||||
|  |     _auth_users: Optional[AuthUserRepositoryABC] = None | ||||||
|  |     _auth: Optional[AuthServiceABC] = None | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def init_authorize(cls, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC): | ||||||
|  |         cls._auth_users = auth_users | ||||||
|  |         cls._auth = auth | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def authorize(cls, f: Callable = None, role: AuthRoleEnum = None): | ||||||
|  |         if f is None: | ||||||
|  |             return functools.partial(cls.authorize, role=role) | ||||||
|  |  | ||||||
|  |         @wraps(f) | ||||||
|  |         async def decorator(*args, **kwargs): | ||||||
|  |             token = None | ||||||
|  |             if 'Authorization' in request.headers: | ||||||
|  |                 bearer = request.headers.get('Authorization') | ||||||
|  |                 token = bearer.split()[1] | ||||||
|  |  | ||||||
|  |             if token is None: | ||||||
|  |                 ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token not set') | ||||||
|  |                 error = ErrorDTO(ex.error_code, ex.message) | ||||||
|  |                 return jsonify(error.to_dict()), 401 | ||||||
|  |  | ||||||
|  |             if cls._auth_users is None or cls._auth is None: | ||||||
|  |                 ex = ServiceException(ServiceErrorCode.Unauthorized, f'Authorize is not initialized') | ||||||
|  |                 error = ErrorDTO(ex.error_code, ex.message) | ||||||
|  |                 return jsonify(error.to_dict()), 401 | ||||||
|  |  | ||||||
|  |             if not cls._auth.verify_login(token): | ||||||
|  |                 ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token expired') | ||||||
|  |                 error = ErrorDTO(ex.error_code, ex.message) | ||||||
|  |                 return jsonify(error.to_dict()), 401 | ||||||
|  |  | ||||||
|  |             token = cls._auth.decode_token(token) | ||||||
|  |             if token is None or 'email' not in token: | ||||||
|  |                 ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token invalid') | ||||||
|  |                 error = ErrorDTO(ex.error_code, ex.message) | ||||||
|  |                 return jsonify(error.to_dict()), 401 | ||||||
|  |  | ||||||
|  |             user = cls._auth_users.get_auth_user_by_email(token['email']) | ||||||
|  |             if user is None: | ||||||
|  |                 ex = ServiceException(ServiceErrorCode.Unauthorized, f'Token invalid') | ||||||
|  |                 error = ErrorDTO(ex.error_code, ex.message) | ||||||
|  |                 return jsonify(error.to_dict()), 401 | ||||||
|  |  | ||||||
|  |             if role is not None and user.auth_role.value < role.value: | ||||||
|  |                 ex = ServiceException(ServiceErrorCode.Unauthorized, f'Role {role} required') | ||||||
|  |                 error = ErrorDTO(ex.error_code, ex.message) | ||||||
|  |                 return jsonify(error.to_dict()), 403 | ||||||
|  |  | ||||||
|  |             return await f(*args, **kwargs) | ||||||
|  |  | ||||||
|  |         return decorator | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def route(cls, path=None, **kwargs): | ||||||
|  |         # simple decorator for class based views | ||||||
|  |         def inner(fn): | ||||||
|  |             cross_origin(fn) | ||||||
|  |             cls.registered_routes[path] = (fn, kwargs) | ||||||
|  |             return fn | ||||||
|  |  | ||||||
|  |         return inner | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def get(cls, path=None, **kwargs): | ||||||
|  |         return cls.route(path, methods=['GET'], **kwargs) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def post(cls, path=None, **kwargs): | ||||||
|  |         return cls.route(path, methods=['POST'], **kwargs) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def head(cls, path=None, **kwargs): | ||||||
|  |         return cls.route(path, methods=['HEAD'], **kwargs) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def put(cls, path=None, **kwargs): | ||||||
|  |         return cls.route(path, methods=['PUT'], **kwargs) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def delete(cls, path=None, **kwargs): | ||||||
|  |         return cls.route(path, methods=['DELETE'], **kwargs) | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/service/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.service' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										537
									
								
								kdb-bot/src/bot_api/service/auth_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										537
									
								
								kdb-bot/src/bot_api/service/auth_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,537 @@ | |||||||
|  | import hashlib | ||||||
|  | import re | ||||||
|  | import textwrap | ||||||
|  | import uuid | ||||||
|  | from datetime import datetime, timedelta, timezone | ||||||
|  | from threading import Thread | ||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | import jwt | ||||||
|  | from cpl_core.database.context import DatabaseContextABC | ||||||
|  | from cpl_core.environment import ApplicationEnvironmentABC | ||||||
|  | from cpl_core.mailing import EMail, EMailClientABC | ||||||
|  | from cpl_core.utils import CredentialManager | ||||||
|  | from cpl_discord.service import DiscordBotServiceABC | ||||||
|  | from cpl_query.extension import List | ||||||
|  | from cpl_translation import TranslatePipe | ||||||
|  | from flask import request | ||||||
|  |  | ||||||
|  | from bot_api.abc.auth_service_abc import AuthServiceABC | ||||||
|  | from bot_api.configuration.authentication_settings import AuthenticationSettings | ||||||
|  | from bot_api.configuration.frontend_settings import FrontendSettings | ||||||
|  | from bot_api.exception.service_error_code_enum import ServiceErrorCode | ||||||
|  | from bot_api.exception.service_exception import ServiceException | ||||||
|  | from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria | ||||||
|  | from bot_api.logging.api_logger import ApiLogger | ||||||
|  | from bot_api.model.auth_user_dto import AuthUserDTO | ||||||
|  | from bot_api.model.auth_user_filtered_result_dto import AuthUserFilteredResultDTO | ||||||
|  | from bot_api.model.email_string_dto import EMailStringDTO | ||||||
|  | from bot_api.model.o_auth_dto import OAuthDTO | ||||||
|  | from bot_api.model.reset_password_dto import ResetPasswordDTO | ||||||
|  | from bot_api.model.token_dto import TokenDTO | ||||||
|  | from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO | ||||||
|  | from bot_api.transformer.auth_user_transformer import AuthUserTransformer as AUT | ||||||
|  | from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC | ||||||
|  | from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||||
|  | from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  | from bot_data.model.auth_user import AuthUser | ||||||
|  | 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' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthService(AuthServiceABC): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             env: ApplicationEnvironmentABC, | ||||||
|  |             logger: ApiLogger, | ||||||
|  |             bot: DiscordBotServiceABC, | ||||||
|  |             db: DatabaseContextABC, | ||||||
|  |             auth_users: AuthUserRepositoryABC, | ||||||
|  |             users: UserRepositoryABC, | ||||||
|  |             servers: ServerRepositoryABC, | ||||||
|  |             # mailer: MailThread, | ||||||
|  |             mailer: EMailClientABC, | ||||||
|  |             t: TranslatePipe, | ||||||
|  |             auth_settings: AuthenticationSettings, | ||||||
|  |             frontend_settings: FrontendSettings, | ||||||
|  |  | ||||||
|  |     ): | ||||||
|  |         AuthServiceABC.__init__(self) | ||||||
|  |  | ||||||
|  |         self._environment = env | ||||||
|  |         self._logger = logger | ||||||
|  |         self._bot = bot | ||||||
|  |         self._db = db | ||||||
|  |         self._auth_users = auth_users | ||||||
|  |         self._users = users | ||||||
|  |         self._servers = servers | ||||||
|  |         self._mailer = mailer | ||||||
|  |         self._t = t | ||||||
|  |         self._auth_settings = auth_settings | ||||||
|  |         self._frontend_settings = frontend_settings | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def _hash_sha256(password: str, salt: str) -> str: | ||||||
|  |         return hashlib.sha256(f'{password}{salt}'.encode('utf-8')).hexdigest() | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def _is_email_valid(email: str) -> bool: | ||||||
|  |         if re.fullmatch(_email_regex, email) is not None: | ||||||
|  |             return True | ||||||
|  |  | ||||||
|  |         return False | ||||||
|  |  | ||||||
|  |     def generate_token(self, user: AuthUser) -> str: | ||||||
|  |         token = jwt.encode( | ||||||
|  |             payload={ | ||||||
|  |                 'user_id': user.id, | ||||||
|  |                 'email': user.email, | ||||||
|  |                 'role': user.auth_role.value, | ||||||
|  |                 'exp': datetime.now(tz=timezone.utc) + timedelta(days=self._auth_settings.token_expire_time), | ||||||
|  |                 'iss': self._auth_settings.issuer, | ||||||
|  |                 'aud': self._auth_settings.audience | ||||||
|  |             }, | ||||||
|  |             key=CredentialManager.decrypt(self._auth_settings.secret_key) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         return token | ||||||
|  |  | ||||||
|  |     def decode_token(self, token: str) -> dict: | ||||||
|  |         return jwt.decode( | ||||||
|  |             token, | ||||||
|  |             key=CredentialManager.decrypt(self._auth_settings.secret_key), | ||||||
|  |             issuer=self._auth_settings.issuer, | ||||||
|  |             audience=self._auth_settings.audience, | ||||||
|  |             algorithms=['HS256'] | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def get_decoded_token_from_request(self) -> dict: | ||||||
|  |         token = None | ||||||
|  |         if 'Authorization' in request.headers: | ||||||
|  |             bearer = request.headers.get('Authorization') | ||||||
|  |             token = bearer.split()[1] | ||||||
|  |  | ||||||
|  |         if token is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.Unauthorized, f'Token not set') | ||||||
|  |  | ||||||
|  |         return jwt.decode( | ||||||
|  |             token, | ||||||
|  |             key=CredentialManager.decrypt(self._auth_settings.secret_key), | ||||||
|  |             issuer=self._auth_settings.issuer, | ||||||
|  |             audience=self._auth_settings.audience, | ||||||
|  |             algorithms=['HS256'] | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def find_decoded_token_from_request(self) -> Optional[dict]: | ||||||
|  |         token = None | ||||||
|  |         if 'Authorization' in request.headers: | ||||||
|  |             bearer = request.headers.get('Authorization') | ||||||
|  |             token = bearer.split()[1] | ||||||
|  |  | ||||||
|  |         return jwt.decode( | ||||||
|  |             token, | ||||||
|  |             key=CredentialManager.decrypt(self._auth_settings.secret_key), | ||||||
|  |             issuer=self._auth_settings.issuer, | ||||||
|  |             audience=self._auth_settings.audience, | ||||||
|  |             algorithms=['HS256'] | ||||||
|  |         ) if token is not None else None | ||||||
|  |  | ||||||
|  |     def _create_and_save_refresh_token(self, user: AuthUser) -> str: | ||||||
|  |         token = str(uuid.uuid4()) | ||||||
|  |         user.refresh_token = token | ||||||
|  |         user.refresh_token_expire_time = datetime.now() + timedelta(days=self._auth_settings.refresh_token_expire_time) | ||||||
|  |         self._auth_users.update_auth_user(user) | ||||||
|  |         self._db.save_changes() | ||||||
|  |         return token | ||||||
|  |  | ||||||
|  |     def _send_link_mail(self, email: str, subject: str, message: str): | ||||||
|  |         url = self._frontend_settings.url | ||||||
|  |         if not url.endswith('/'): | ||||||
|  |             url = f'{url}/' | ||||||
|  |  | ||||||
|  |         self._mailer.connect() | ||||||
|  |         mail = EMail() | ||||||
|  |         mail.add_header('Mime-Version: 1.0') | ||||||
|  |         mail.add_header('Content-Type: text/plain; charset=utf-8') | ||||||
|  |         mail.add_header('Content-Transfer-Encoding: quoted-printable') | ||||||
|  |         mail.add_receiver(str(email)) | ||||||
|  |         mail.subject = subject | ||||||
|  |         mail.body = textwrap.dedent(f"""{message} | ||||||
|  |         {self._t.transform('api.mail.automatic_mail').format(self._environment.application_name, self._environment.environment_name, self._environment.host_name)} | ||||||
|  |         """) | ||||||
|  |  | ||||||
|  |         thr = Thread(target=self._mailer.send_mail, args=[mail]) | ||||||
|  |         thr.start() | ||||||
|  |  | ||||||
|  |     def _send_confirmation_id_to_user(self, user: AuthUser): | ||||||
|  |         url = self._frontend_settings.url | ||||||
|  |         if not url.endswith('/'): | ||||||
|  |             url = f'{url}/' | ||||||
|  |  | ||||||
|  |         self._send_link_mail( | ||||||
|  |             user.email, | ||||||
|  |             self._t.transform('api.auth.confirmation.subject').format(user.first_name, user.last_name), | ||||||
|  |             self._t.transform('api.auth.confirmation.message').format(url, user.confirmation_id) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def _send_forgot_password_id_to_user(self, user: AuthUser): | ||||||
|  |         url = self._frontend_settings.url | ||||||
|  |         if not url.endswith('/'): | ||||||
|  |             url = f'{url}/' | ||||||
|  |  | ||||||
|  |         self._send_link_mail( | ||||||
|  |             user.email, | ||||||
|  |             self._t.transform('api.auth.forgot_password.subject').format(user.first_name, user.last_name), | ||||||
|  |             self._t.transform('api.auth.forgot_password.message').format(url, user.forgot_password_id) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     async def get_all_auth_users_async(self) -> List[AuthUserDTO]: | ||||||
|  |         result = self._auth_users.get_all_auth_users() \ | ||||||
|  |             .select(lambda x: AUT.to_dto(x)) | ||||||
|  |         return List(AuthUserDTO, result) | ||||||
|  |  | ||||||
|  |     async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO: | ||||||
|  |         users = self._auth_users.get_filtered_auth_users(criteria) | ||||||
|  |         result = users.result.select(lambda x: AUT.to_dto(x)) | ||||||
|  |  | ||||||
|  |         return AuthUserFilteredResultDTO( | ||||||
|  |             List(AuthUserDTO, result), | ||||||
|  |             users.total_count | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO: | ||||||
|  |         try: | ||||||
|  |             # todo: check if logged in user is admin then send mail | ||||||
|  |             user = self._auth_users.get_auth_user_by_email(email) | ||||||
|  |             return AUT.to_dto(user, password=user.password if with_password else None) | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'AuthUser not found', e) | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'User not found {email}') | ||||||
|  |  | ||||||
|  |     async def find_auth_user_by_email_async(self, email: str) -> Optional[AuthUser]: | ||||||
|  |         user = self._auth_users.find_auth_user_by_email(email) | ||||||
|  |         return AUT.to_dto(user) if user is not None else None | ||||||
|  |  | ||||||
|  |     async def add_auth_user_async(self, user_dto: AuthUserDTO): | ||||||
|  |         db_user = self._auth_users.find_auth_user_by_email(user_dto.email) | ||||||
|  |         if db_user is not None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists') | ||||||
|  |  | ||||||
|  |         user = AUT.to_db(user_dto) | ||||||
|  |         if self._auth_users.get_all_auth_users().count() == 0: | ||||||
|  |             user.auth_role = AuthRoleEnum.admin | ||||||
|  |  | ||||||
|  |         user.password_salt = uuid.uuid4() | ||||||
|  |         user.password = self._hash_sha256(user_dto.password, user.password_salt) | ||||||
|  |         if not self._is_email_valid(user.email): | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, 'Invalid E-Mail address') | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             user.confirmation_id = uuid.uuid4() | ||||||
|  |             self._auth_users.add_auth_user(user) | ||||||
|  |             self._send_confirmation_id_to_user(user) | ||||||
|  |             self._db.save_changes() | ||||||
|  |             self._logger.info(__name__, f'Added auth user with E-Mail: {user_dto.email}') | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'Cannot add user with E-Mail {user_dto.email}', e) | ||||||
|  |             raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail") | ||||||
|  |  | ||||||
|  |     async def add_auth_user_by_oauth_async(self, dto: OAuthDTO): | ||||||
|  |         db_user = self._auth_users.find_auth_user_by_email(dto.user.email) | ||||||
|  |  | ||||||
|  |         if db_user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'User not found') | ||||||
|  |  | ||||||
|  |         if db_user.oauth_id != dto.oauth_id: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'Wrong OAuthId') | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             db_user.first_name = dto.user.first_name | ||||||
|  |             db_user.last_name = dto.user.last_name | ||||||
|  |             db_user.password_salt = uuid.uuid4() | ||||||
|  |             db_user.password = self._hash_sha256(dto.user.password, db_user.password_salt) | ||||||
|  |             db_user.oauth_id = None | ||||||
|  |             db_user.confirmation_id = uuid.uuid4() | ||||||
|  |             self._send_confirmation_id_to_user(db_user) | ||||||
|  |             self._auth_users.update_auth_user(db_user) | ||||||
|  |             self._logger.info(__name__, f'Added auth user with E-Mail: {dto.user.email}') | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'Cannot add user with E-Mail {dto.user.email}', e) | ||||||
|  |             raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail") | ||||||
|  |  | ||||||
|  |         self._db.save_changes() | ||||||
|  |  | ||||||
|  |     async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO: | ||||||
|  |         db_auth_user = self._auth_users.find_auth_user_by_email(user_dto.email) | ||||||
|  |  | ||||||
|  |         # user exists | ||||||
|  |         if db_auth_user is not None and db_auth_user.users.count() > 0: | ||||||
|  |             # raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists') | ||||||
|  |             self._logger.debug(__name__, f'Discord user already exists') | ||||||
|  |             return OAuthDTO(AUT.to_dto(db_auth_user), None) | ||||||
|  |  | ||||||
|  |         # user exists but discord user id not set | ||||||
|  |         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') | ||||||
|  |             # users = self._users.get_users_by_discord_id(user_dto.user_id) | ||||||
|  |             # add auth_user to user refs | ||||||
|  |             db_auth_user.oauth_id = None | ||||||
|  |  | ||||||
|  |         else: | ||||||
|  |             # user does not exists | ||||||
|  |             self._logger.debug(__name__, f'Auth user does not exist') | ||||||
|  |             try: | ||||||
|  |                 user_dto.user_id = self._users.get_users_by_discord_id(user_dto.user_id).single().user_id | ||||||
|  |             except Exception as e: | ||||||
|  |                 self._logger.error(__name__, f'User not found') | ||||||
|  |                 user_dto.user_id = None | ||||||
|  |  | ||||||
|  |             await self.add_auth_user_async(user_dto) | ||||||
|  |             db_auth_user = self._auth_users.get_auth_user_by_email(user_dto.email) | ||||||
|  |             db_auth_user.oauth_id = uuid.uuid4() | ||||||
|  |  | ||||||
|  |         for g in self._bot.guilds: | ||||||
|  |             member = g.get_member(int(dc_id)) | ||||||
|  |             if member is None: | ||||||
|  |                 continue | ||||||
|  |  | ||||||
|  |             server = self._servers.get_server_by_discord_id(g.id) | ||||||
|  |             users = self._users.get_users_by_discord_id(dc_id) | ||||||
|  |             for user in users: | ||||||
|  |                 if user.server.server_id != server.server_id: | ||||||
|  |                     continue | ||||||
|  |                 self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_auth_user, user)) | ||||||
|  |  | ||||||
|  |         self._auth_users.update_auth_user(db_auth_user) | ||||||
|  |         self._db.save_changes() | ||||||
|  |         return OAuthDTO(AUT.to_dto(db_auth_user), db_auth_user.oauth_id) | ||||||
|  |  | ||||||
|  |     async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): | ||||||
|  |         if update_user_dto is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'User is empty') | ||||||
|  |  | ||||||
|  |         if update_user_dto.auth_user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'Existing user is empty') | ||||||
|  |  | ||||||
|  |         if update_user_dto.new_auth_user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'New user is empty') | ||||||
|  |  | ||||||
|  |         if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(update_user_dto.new_auth_user.email): | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'Invalid E-Mail') | ||||||
|  |  | ||||||
|  |         user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email) | ||||||
|  |         if user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'User not found') | ||||||
|  |  | ||||||
|  |         if user.confirmation_id is not None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed') | ||||||
|  |  | ||||||
|  |         # 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: | ||||||
|  |             user.first_name = update_user_dto.new_auth_user.first_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: | ||||||
|  |             user.last_name = update_user_dto.new_auth_user.last_name | ||||||
|  |  | ||||||
|  |         # 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: | ||||||
|  |             user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email) | ||||||
|  |             if user_by_new_e_mail is not None: | ||||||
|  |                 raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists') | ||||||
|  |             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) | ||||||
|  |         if update_user_dto.auth_user.password != user.password: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'Wrong password') | ||||||
|  |  | ||||||
|  |         # update password | ||||||
|  |         if update_user_dto.new_auth_user.password is not None and self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt) != user.password: | ||||||
|  |             user.password_salt = uuid.uuid4() | ||||||
|  |             user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt) | ||||||
|  |  | ||||||
|  |         self._auth_users.update_auth_user(user) | ||||||
|  |         self._db.save_changes() | ||||||
|  |  | ||||||
|  |     async def update_user_as_admin_async(self, update_user_dto: UpdateAuthUserDTO): | ||||||
|  |         if update_user_dto is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'User is empty') | ||||||
|  |  | ||||||
|  |         if update_user_dto.auth_user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'Existing user is empty') | ||||||
|  |  | ||||||
|  |         if update_user_dto.new_auth_user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'New user is empty') | ||||||
|  |  | ||||||
|  |         if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(update_user_dto.new_auth_user.email): | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'Invalid E-Mail') | ||||||
|  |  | ||||||
|  |         user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email) | ||||||
|  |         if user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'User not found') | ||||||
|  |  | ||||||
|  |         if user.confirmation_id is not None and update_user_dto.new_auth_user.is_confirmed: | ||||||
|  |             user.confirmation_id = None | ||||||
|  |         elif user.confirmation_id is None and not update_user_dto.new_auth_user.is_confirmed: | ||||||
|  |             user.confirmation_id = uuid.uuid4() | ||||||
|  |         # else | ||||||
|  |         #     raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed') | ||||||
|  |  | ||||||
|  |         # 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: | ||||||
|  |             user.first_name = update_user_dto.new_auth_user.first_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: | ||||||
|  |             user.last_name = update_user_dto.new_auth_user.last_name | ||||||
|  |  | ||||||
|  |         # 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: | ||||||
|  |             user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email) | ||||||
|  |             if user_by_new_e_mail is not None: | ||||||
|  |                 raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists') | ||||||
|  |             user.email = update_user_dto.new_auth_user.email | ||||||
|  |  | ||||||
|  |         # update password | ||||||
|  |         if update_user_dto.new_auth_user.password is not None and update_user_dto.change_password and user.password != self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt): | ||||||
|  |             user.password_salt = uuid.uuid4() | ||||||
|  |             user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt) | ||||||
|  |  | ||||||
|  |         # 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: | ||||||
|  |             user.auth_role = update_user_dto.new_auth_user.auth_role | ||||||
|  |  | ||||||
|  |         self._auth_users.update_auth_user(user) | ||||||
|  |         self._db.save_changes() | ||||||
|  |  | ||||||
|  |     async def delete_auth_user_by_email_async(self, email: str): | ||||||
|  |         try: | ||||||
|  |             user = self._auth_users.get_auth_user_by_email(email) | ||||||
|  |             self._auth_users.delete_auth_user(user) | ||||||
|  |             self._db.save_changes() | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'Cannot delete user', e) | ||||||
|  |             raise ServiceException(ServiceErrorCode.UnableToDelete, f'Cannot delete user by mail {email}') | ||||||
|  |  | ||||||
|  |     async def delete_auth_user_async(self, user_dto: AuthUser): | ||||||
|  |         try: | ||||||
|  |             self._auth_users.delete_auth_user(AUT.to_db(user_dto)) | ||||||
|  |             self._db.save_changes() | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'Cannot delete user', e) | ||||||
|  |             raise ServiceException(ServiceErrorCode.UnableToDelete, f'Cannot delete user by mail {user_dto.email}') | ||||||
|  |  | ||||||
|  |     def verify_login(self, token_str: str) -> bool: | ||||||
|  |         try: | ||||||
|  |             token = self.decode_token(token_str) | ||||||
|  |             if token is None or 'email' not in token: | ||||||
|  |                 raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid') | ||||||
|  |  | ||||||
|  |             user = self._auth_users.find_auth_user_by_email(token['email']) | ||||||
|  |             if user is None: | ||||||
|  |                 raise ServiceException(ServiceErrorCode.InvalidData, 'Token expired') | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'Token invalid', e) | ||||||
|  |             return False | ||||||
|  |  | ||||||
|  |         return True | ||||||
|  |  | ||||||
|  |     async def login_async(self, user_dto: AuthUser) -> 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: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found') | ||||||
|  |  | ||||||
|  |         user_dto.password = self._hash_sha256(user_dto.password, db_user.password_salt) | ||||||
|  |         if db_user.password != user_dto.password: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, 'Wrong password') | ||||||
|  |  | ||||||
|  |         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: | ||||||
|  |         if token_dto is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'Token not set') | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             token = self.decode_token(token_dto.token) | ||||||
|  |             if token is None or 'email' not in token: | ||||||
|  |                 raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid') | ||||||
|  |  | ||||||
|  |             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(): | ||||||
|  |                 raise ServiceException(ServiceErrorCode.InvalidData, 'Token expired') | ||||||
|  |  | ||||||
|  |             return TokenDTO(self.generate_token(user), self._create_and_save_refresh_token(user)) | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'Refreshing token failed', e) | ||||||
|  |             return TokenDTO('', '') | ||||||
|  |  | ||||||
|  |     async def revoke_async(self, token_dto: TokenDTO): | ||||||
|  |         if token_dto is None or token_dto.token is None or token_dto.refresh_token is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, 'Token not set') | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             token = self.decode_token(token_dto.token) | ||||||
|  |  | ||||||
|  |             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(): | ||||||
|  |                 raise ServiceException(ServiceErrorCode.InvalidData, 'Token expired') | ||||||
|  |  | ||||||
|  |             user.refresh_token = None | ||||||
|  |             self._auth_users.update_auth_user(user) | ||||||
|  |             self._db.save_changes() | ||||||
|  |         except Exception as e: | ||||||
|  |             self._logger.error(__name__, f'Refreshing token failed', e) | ||||||
|  |  | ||||||
|  |     async def confirm_email_async(self, id: str) -> bool: | ||||||
|  |         user = self._auth_users.find_auth_user_by_confirmation_id(id) | ||||||
|  |         if user is None: | ||||||
|  |             return False | ||||||
|  |  | ||||||
|  |         user.confirmation_id = None | ||||||
|  |         self._auth_users.update_auth_user(user) | ||||||
|  |         self._db.save_changes() | ||||||
|  |         return True | ||||||
|  |  | ||||||
|  |     async def forgot_password_async(self, email: str): | ||||||
|  |         user = self._auth_users.find_auth_user_by_email(email) | ||||||
|  |         if user is None: | ||||||
|  |             return | ||||||
|  |  | ||||||
|  |         user.forgot_password_id = uuid.uuid4() | ||||||
|  |         self._auth_users.update_auth_user(user) | ||||||
|  |         self._send_forgot_password_id_to_user(user) | ||||||
|  |         self._db.save_changes() | ||||||
|  |  | ||||||
|  |     async def confirm_forgot_password_async(self, id: str) -> EMailStringDTO: | ||||||
|  |         user = self._auth_users.find_auth_user_by_forgot_password_id(id) | ||||||
|  |         return EMailStringDTO(user.email) | ||||||
|  |  | ||||||
|  |     async def reset_password_async(self, rp_dto: ResetPasswordDTO): | ||||||
|  |         user = self._auth_users.find_auth_user_by_forgot_password_id(rp_dto.id) | ||||||
|  |         if user is None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, f'User by forgot password id {rp_dto.id} not found') | ||||||
|  |  | ||||||
|  |         if user.confirmation_id is not None: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidUser, f'E-Mail not confirmed') | ||||||
|  |  | ||||||
|  |         if user.password is None or rp_dto.password == '': | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, f'Password not set') | ||||||
|  |  | ||||||
|  |         user.password_salt = uuid.uuid4() | ||||||
|  |         user.password = self._hash_sha256(rp_dto.password, user.password_salt) | ||||||
|  |         user.forgot_password_id = None | ||||||
|  |         self._auth_users.update_auth_user(user) | ||||||
|  |         self._db.save_changes() | ||||||
							
								
								
									
										105
									
								
								kdb-bot/src/bot_api/service/discord_service.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								kdb-bot/src/bot_api/service/discord_service.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | |||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | from cpl_discord.service import DiscordBotServiceABC | ||||||
|  | from cpl_query.extension import List | ||||||
|  | from flask import jsonify | ||||||
|  |  | ||||||
|  | from bot_api.abc.auth_service_abc import AuthServiceABC | ||||||
|  | from bot_api.exception.service_error_code_enum import ServiceErrorCode | ||||||
|  | from bot_api.exception.service_exception import ServiceException | ||||||
|  | from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria | ||||||
|  | from bot_api.model.discord.server_dto import ServerDTO | ||||||
|  | from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO | ||||||
|  | from bot_api.model.error_dto import ErrorDTO | ||||||
|  | from bot_api.transformer.server_transformer import ServerTransformer | ||||||
|  | from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC | ||||||
|  | from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||||
|  | from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  | from bot_data.model.server import Server | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DiscordService: | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |             self, | ||||||
|  |             bot: DiscordBotServiceABC, | ||||||
|  |             servers: ServerRepositoryABC, | ||||||
|  |             auth: AuthServiceABC, | ||||||
|  |             auth_users: AuthUserRepositoryABC, | ||||||
|  |             users: UserRepositoryABC, | ||||||
|  |     ): | ||||||
|  |         self._bot = bot | ||||||
|  |         self._servers = servers | ||||||
|  |         self._auth = auth | ||||||
|  |         self._auth_users = auth_users | ||||||
|  |         self._users = users | ||||||
|  |  | ||||||
|  |     def _to_dto(self, x: Server) -> Optional[ServerDTO]: | ||||||
|  |         guild = self._bot.get_guild(x.discord_server_id) | ||||||
|  |         if guild is None: | ||||||
|  |             return ServerTransformer.to_dto( | ||||||
|  |                 x, | ||||||
|  |                 '', | ||||||
|  |                 0, | ||||||
|  |                 None | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         return ServerTransformer.to_dto( | ||||||
|  |             x, | ||||||
|  |             guild.name, | ||||||
|  |             guild.member_count, | ||||||
|  |             guild.icon | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     async def get_all_servers(self) -> List[ServerDTO]: | ||||||
|  |         servers = List(ServerDTO, self._servers.get_servers()) | ||||||
|  |         return servers.select(self._to_dto).where(lambda x: x.name != '') | ||||||
|  |  | ||||||
|  |     async def get_all_servers_by_user(self) -> List[ServerDTO]: | ||||||
|  |         token = self._auth.get_decoded_token_from_request() | ||||||
|  |         if token is None or 'email' not in token or 'role' not in token: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid') | ||||||
|  |  | ||||||
|  |         role = AuthRoleEnum(token['role']) | ||||||
|  |         servers = self._servers.get_servers() | ||||||
|  |         if role != AuthRoleEnum.admin: | ||||||
|  |             auth_user = self._auth_users.find_auth_user_by_email(token['email']) | ||||||
|  |             if auth_user is not None: | ||||||
|  |                 user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) | ||||||
|  |                 servers = servers.where(lambda x: x.server_id in user_ids) | ||||||
|  |  | ||||||
|  |         servers = List(ServerDTO, servers) | ||||||
|  |         return servers.select(self._to_dto).where(lambda x: x.name != '') | ||||||
|  |  | ||||||
|  |     async def get_filtered_servers_async(self, criteria: ServerSelectCriteria) -> ServerFilteredResultDTO: | ||||||
|  |         token = self._auth.get_decoded_token_from_request() | ||||||
|  |         if token is None or 'email' not in token or 'role' not in token: | ||||||
|  |             raise ServiceException(ServiceErrorCode.InvalidData, 'Token invalid') | ||||||
|  |  | ||||||
|  |         role = AuthRoleEnum(token['role']) | ||||||
|  |         filtered_result = self._servers.get_filtered_servers(criteria) | ||||||
|  |         # filter out servers, where the user not exists | ||||||
|  |         if role != AuthRoleEnum.admin: | ||||||
|  |             auth_user = self._auth_users.find_auth_user_by_email(token['email']) | ||||||
|  |             if auth_user is not None: | ||||||
|  |                 user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) | ||||||
|  |                 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 != '') | ||||||
|  |         result = List(ServerDTO, servers) | ||||||
|  |  | ||||||
|  |         if criteria.name is not None and criteria.name != '': | ||||||
|  |             result = result.where(lambda x: criteria.name.lower() in x.name.lower() or x.name.lower() == criteria.name.lower()) | ||||||
|  |  | ||||||
|  |         return ServerFilteredResultDTO( | ||||||
|  |             List(ServerDTO, result), | ||||||
|  |             servers.count() | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     async def get_server_by_id_async(self, id: int) -> ServerDTO: | ||||||
|  |         server = self._servers.get_server_by_id(id) | ||||||
|  |         guild = self._bot.get_guild(server.discord_server_id) | ||||||
|  |  | ||||||
|  |         server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon) | ||||||
|  |         return server_dto | ||||||
							
								
								
									
										26
									
								
								kdb-bot/src/bot_api/transformer/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								kdb-bot/src/bot_api/transformer/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  |  | ||||||
|  | """ | ||||||
|  | bot Keksdose bot | ||||||
|  | ~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | Discord bot  for the Keksdose discord Server | ||||||
|  |  | ||||||
|  | :copyright: (c) 2022 sh-edraft.de | ||||||
|  | :license: MIT, see LICENSE for more details. | ||||||
|  |  | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | __title__ = 'bot_api.transformer' | ||||||
|  | __author__ = 'Sven Heidemann' | ||||||
|  | __license__ = 'MIT' | ||||||
|  | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
|  | __version__ = '0.3.dev25' | ||||||
|  |  | ||||||
|  | from collections import namedtuple | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # imports: | ||||||
|  |  | ||||||
|  | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
|  | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
							
								
								
									
										38
									
								
								kdb-bot/src/bot_api/transformer/auth_user_transformer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								kdb-bot/src/bot_api/transformer/auth_user_transformer.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | from datetime import datetime, timezone | ||||||
|  |  | ||||||
|  | from bot_api.abc.transformer_abc import TransformerABC | ||||||
|  | from bot_api.model.auth_user_dto import AuthUserDTO | ||||||
|  | from bot_data.model.auth_role_enum import AuthRoleEnum | ||||||
|  | from bot_data.model.auth_user import AuthUser | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthUserTransformer(TransformerABC): | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def to_db(dto: AuthUserDTO) -> AuthUser: | ||||||
|  |         return AuthUser( | ||||||
|  |             dto.first_name, | ||||||
|  |             dto.last_name, | ||||||
|  |             dto.email, | ||||||
|  |             dto.password, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             datetime.now(), | ||||||
|  |             AuthRoleEnum.normal if dto.auth_role is None else AuthRoleEnum(dto.auth_role), | ||||||
|  |             auth_user_id=0 if dto.id is None else dto.id | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def to_dto(db: AuthUser, password: str = None) -> AuthUserDTO: | ||||||
|  |         return AuthUserDTO( | ||||||
|  |             db.id, | ||||||
|  |             db.first_name, | ||||||
|  |             db.last_name, | ||||||
|  |             db.email, | ||||||
|  |             '' if password is None else password, | ||||||
|  |             db.confirmation_id, | ||||||
|  |             db.auth_role | ||||||
|  |         ) | ||||||
							
								
								
									
										24
									
								
								kdb-bot/src/bot_api/transformer/server_transformer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								kdb-bot/src/bot_api/transformer/server_transformer.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | from typing import Optional | ||||||
|  |  | ||||||
|  | import discord | ||||||
|  |  | ||||||
|  | from bot_api.abc.transformer_abc import TransformerABC | ||||||
|  | from bot_api.model.discord.server_dto import ServerDTO | ||||||
|  | from bot_data.model.server import Server | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ServerTransformer(TransformerABC): | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def to_db(dto: ServerDTO) -> Server: | ||||||
|  |         return Server(dto.discord_id) | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def to_dto(db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]) -> ServerDTO: | ||||||
|  |         return ServerDTO( | ||||||
|  |             db.server_id, | ||||||
|  |             db.discord_server_id, | ||||||
|  |             name, | ||||||
|  |             member_count, | ||||||
|  |             icon_url.url if icon_url is not None else None, | ||||||
|  |         ) | ||||||
| @@ -15,7 +15,7 @@ __title__ = 'bot_core' | |||||||
| __author__ = 'Sven Heidemann' | __author__ = 'Sven Heidemann' | ||||||
| __license__ = 'MIT' | __license__ = 'MIT' | ||||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
| __version__ = '0.2.3' | __version__ = '0.3.dev25' | ||||||
| 
 | 
 | ||||||
| from collections import namedtuple | from collections import namedtuple | ||||||
| 
 | 
 | ||||||
| @@ -23,4 +23,4 @@ from collections import namedtuple | |||||||
| # imports | # imports | ||||||
| 
 | 
 | ||||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
| version_info = VersionInfo(major='0', minor='2', micro='3') | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
| @@ -15,7 +15,7 @@ __title__ = 'bot_core.service' | |||||||
| __author__ = 'Sven Heidemann' | __author__ = 'Sven Heidemann' | ||||||
| __license__ = 'MIT' | __license__ = 'MIT' | ||||||
| __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | __copyright__ = 'Copyright (c) 2022 sh-edraft.de' | ||||||
| __version__ = '0.2.3' | __version__ = '0.3.dev25' | ||||||
| 
 | 
 | ||||||
| from collections import namedtuple | from collections import namedtuple | ||||||
| 
 | 
 | ||||||
| @@ -23,4 +23,4 @@ from collections import namedtuple | |||||||
| # imports: | # imports: | ||||||
| 
 | 
 | ||||||
| VersionInfo = namedtuple('VersionInfo', 'major minor micro') | VersionInfo = namedtuple('VersionInfo', 'major minor micro') | ||||||
| version_info = VersionInfo(major='0', minor='2', micro='3') | version_info = VersionInfo(major='0', minor='3', micro='dev25') | ||||||
| @@ -3,6 +3,7 @@ from typing import Union | |||||||
| 
 | 
 | ||||||
| import discord | import discord | ||||||
| from cpl_query.extension import List | from cpl_query.extension import List | ||||||
|  | from discord import Interaction | ||||||
| from discord.ext.commands import Context | from discord.ext.commands import Context | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @@ -25,3 +26,6 @@ class MessageServiceABC(ABC): | |||||||
| 
 | 
 | ||||||
|     @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_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 | ||||||
|  | 
 | ||||||
|  |     @abstractmethod | ||||||
|  |     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 | ||||||
| @@ -2,9 +2,9 @@ | |||||||
|   "ProjectSettings": { |   "ProjectSettings": { | ||||||
|     "Name": "bot-core", |     "Name": "bot-core", | ||||||
|     "Version": { |     "Version": { | ||||||
|       "Major": "1", |       "Major": "0", | ||||||
|       "Minor": "0", |       "Minor": "3", | ||||||
|       "Micro": "0" |       "Micro": "dev70" | ||||||
|     }, |     }, | ||||||
|     "Author": "Sven Heidemann", |     "Author": "Sven Heidemann", | ||||||
|     "AuthorEmail": "sven.heidemann@sh-edraft.de", |     "AuthorEmail": "sven.heidemann@sh-edraft.de", | ||||||
| @@ -16,15 +16,13 @@ | |||||||
|     "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" |       "cpl-core>=0.3.dev70" | ||||||
|     ], |     ], | ||||||
|     "DevDependencies": [ |     "DevDependencies": [ | ||||||
|       "cpl-cli>=2022.10.0" |       "cpl-cli==2022.10.0" | ||||||
|     ], |     ], | ||||||
|     "PythonVersion": ">=3.10.4", |     "PythonVersion": ">=3.10.4", | ||||||
|     "PythonPath": { |     "PythonPath": {}, | ||||||
|       "linux": "" |  | ||||||
|     }, |  | ||||||
|     "Classifiers": [] |     "Classifiers": [] | ||||||
|   }, |   }, | ||||||
|   "BuildSettings": { |   "BuildSettings": { | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user