Compare commits
192 Commits
Author | SHA1 | Date | |
---|---|---|---|
40419c9a0b | |||
dadaa6ac09 | |||
10ba511158 | |||
09a4ace867 | |||
b436daeb35 | |||
daa031bc57 | |||
286c653252 | |||
|
3eaae4679f | ||
|
39079b2b58 | ||
|
fcc5b882b7 | ||
42826a1914 | |||
2ae0a99783 | |||
51fd8f7a8b | |||
291efd2319 | |||
0b17b27bd0 | |||
f800a11f41 | |||
7e6485459b | |||
789186454e | |||
49aa2f3aa3 | |||
199c269804 | |||
adc74d6288 | |||
c6e52039cb | |||
4955eb3a19 | |||
9d17070d02 | |||
f417eca644 | |||
a10724a495 | |||
e3ac78f97b | |||
68c1bc0bc3 | |||
be5567c1fd | |||
e34fbb60aa | |||
f03ee54703 | |||
9bae6c3c13 | |||
e73ebeb052 | |||
5fce7318ae | |||
d1298606f3 | |||
ca361b63cb | |||
d5de1991eb | |||
22b0c3ca6a | |||
1d09ad80bf | |||
c949efea50 | |||
0fd99cc6ba | |||
2c29b45f5a | |||
b8e340f661 | |||
026dfe0dfb | |||
d27964372d | |||
e15ae555be | |||
ce70e816fe | |||
60172e0cfe | |||
62d56a2247 | |||
be692326d6 | |||
074fa1ed46 | |||
93269908bc | |||
0bb5024c6a | |||
9c7b00e259 | |||
1a5767edf0 | |||
7bcd632b59 | |||
20aedba23d | |||
1d4a6c3e3b | |||
61101eb576 | |||
14ecc46d92 | |||
01cf17ef86 | |||
c5d2639e0a | |||
6356d455f4 | |||
0029fc4ac8 | |||
cbb73d7c86 | |||
68694d2e13 | |||
762ae5fd4d | |||
ed1cb24e9c | |||
e489787f01 | |||
d668d0138f | |||
7c77768697 | |||
8108f83b92 | |||
afd024e991 | |||
e69955e6d2 | |||
df26a66562 | |||
c6f460c0ab | |||
3390e09ef3 | |||
ed9a3bc90c | |||
2e24a3b1f2 | |||
f4c340796e | |||
4edda07cee | |||
e951baa358 | |||
2d261a6222 | |||
1f095c9415 | |||
a8551f2f95 | |||
3806c36571 | |||
a5f710177e | |||
5a91e31964 | |||
112b9d6208 | |||
be810a6533 | |||
9ebbd7ccf7 | |||
0b5f47ab8a | |||
|
00a0c182be | ||
|
d7105b9d19 | ||
|
73fedd31dc | ||
|
c9a5f648a2 | ||
|
76642112ab | ||
|
5e646d394b | ||
|
2ab2ef3776 | ||
7780b43e11 | |||
|
ffad565520 | ||
f033eeaf87 | |||
3b4b81eba0 | |||
|
4e00da99b5 | ||
3fc3b9548a | |||
9cbc589d62 | |||
|
e351b98fe4 | ||
a2e52e473c | |||
463456711d | |||
4d69250342 | |||
|
276910c86d | ||
b0c75fa651 | |||
|
e81449031e | ||
4176db9f91 | |||
14d543a587 | |||
d1740edda0 | |||
|
1edcfe58d2 | ||
2c7755310d | |||
aeef7ed477 | |||
e83982fc2a | |||
|
acc106a567 | ||
67696bc63c | |||
|
c9f28ddc14 | ||
|
b903ec5434 | ||
|
81bf7b6250 | ||
|
bef8ea0a25 | ||
558b6628a3 | |||
15af3b1f63 | |||
a2ebf4e3b5 | |||
|
3d56ef1dd5 | ||
|
b429d60bcd | ||
7edef25617 | |||
4d7c67a3b6 | |||
426772910f | |||
04179ce906 | |||
|
c3e1aaf40f | ||
49ec7ea931 | |||
|
c0d38817d4 | ||
31682f2b83 | |||
|
a56bdf39f7 | ||
89c31c6392 | |||
0730c5f915 | |||
|
ae7f6543f3 | ||
|
711819cdea | ||
85931926c3 | |||
d99cec79b9 | |||
|
8461d793de | ||
|
baa86b75e7 | ||
|
652a3eeb47 | ||
03d427b520 | |||
7a9e127df3 | |||
118ba99b92 | |||
2914308d65 | |||
732d28e5dc | |||
cb8c090ab3 | |||
5cbd40ec03 | |||
3832f9b8fc | |||
d6b65c42cc | |||
6509f628ca | |||
5b61de0bf1 | |||
5afbdb9b82 | |||
880fe8a4c7 | |||
12492cf596 | |||
9584b34f8f | |||
5e1caf713c | |||
c254114987 | |||
81499ef8e6 | |||
b0b646bb2b | |||
e8e6a28d87 | |||
26e1ed7496 | |||
d2c233a855 | |||
2176037d08 | |||
16546b4d3c | |||
9c25ec9f24 | |||
d413ace721 | |||
647e847d17 | |||
f2ee3d64f6 | |||
4763c41b10 | |||
562caeb10b | |||
a3bf5535f6 | |||
26a93c5ea1 | |||
abe9a7b472 | |||
97a3ba24a6 | |||
b1becbe866 | |||
059e345751 | |||
744501b3c2 | |||
056335e84b | |||
eda1caf36a | |||
c82e8e3065 | |||
bca2e02cc2 | |||
1927860206 | |||
24ae39d9f6 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -138,3 +138,7 @@ dmypy.json
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# custom vs code
|
||||
PythonImportHelper-v2-Completion.json
|
||||
appsettings.*.json
|
||||
|
||||
|
31
.vscode/launch.json
vendored
Normal file
31
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python: Aktuelle Datei",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Gismo",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}/src/gismo",
|
||||
"program": "main.py",
|
||||
"console": "integratedTerminal",
|
||||
"args": [
|
||||
"--customer=sh-edraft.de"
|
||||
],
|
||||
"env": {
|
||||
"CPL_NAME": "Gismo",
|
||||
"GISMO_ENVIRONMENT": "development",
|
||||
"PYTHONPATH": "${workspaceFolder}/src/:$PYTHONPATH"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
24
.vscode/settings.json
vendored
Normal file
24
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.activeBackground": "#93e6fc",
|
||||
"activityBar.activeBorder": "#fa45d4",
|
||||
"activityBar.background": "#93e6fc",
|
||||
"activityBar.foreground": "#15202b",
|
||||
"activityBar.inactiveForeground": "#15202b99",
|
||||
"activityBarBadge.background": "#fa45d4",
|
||||
"activityBarBadge.foreground": "#15202b",
|
||||
"sash.hoverBorder": "#93e6fc",
|
||||
"statusBar.background": "#61dafb",
|
||||
"statusBar.foreground": "#15202b",
|
||||
"statusBarItem.hoverBackground": "#2fcefa",
|
||||
"statusBarItem.remoteBackground": "#61dafb",
|
||||
"statusBarItem.remoteForeground": "#15202b",
|
||||
"titleBar.activeBackground": "#61dafb",
|
||||
"titleBar.activeForeground": "#15202b",
|
||||
"titleBar.inactiveBackground": "#61dafb99",
|
||||
"titleBar.inactiveForeground": "#15202b99"
|
||||
},
|
||||
"peacock.color": "#61dafb",
|
||||
"python.pythonPath": "${workspaceRoot}/venv/bin/python",
|
||||
"python.defaultInterpreterPath": "${workspaceRoot}/venv/bin/python",
|
||||
}
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
MIT License Copyright (c) <year> <copyright holders>
|
||||
MIT License Copyright (c) 2021-2022 sh-edraft.de
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
29
cpl-workspace.json
Normal file
29
cpl-workspace.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"WorkspaceSettings": {
|
||||
"DefaultProject": "gismo",
|
||||
"Projects": {
|
||||
"gismo": "src/gismo/gismo.json",
|
||||
"gismo-cli": "src/gismo_cli/gismo-cli.json",
|
||||
"gismo-core": "src/gismo_core/gismo-core.json",
|
||||
"gismo-data": "src/gismo_data/gismo-data.json",
|
||||
"modules-core": "src/modules_core/modules-core.json",
|
||||
"boot-log": "src/modules/boot_log/boot-log.json",
|
||||
"level-generator": "tools/level_generator/level-generator.json",
|
||||
"ontime-calculator": "tools/ontime_calculator/ontime-calculator.json",
|
||||
"database": "src/modules/database/database.json",
|
||||
"base": "src/modules/base/base.json"
|
||||
},
|
||||
"Scripts": {
|
||||
"build-start": "cd src/gismo_cli; echo 'gismo-cli:'; cpl build; cd ../gismo; echo 'gismo:'; cpl build; cd ../../dist/gismo/build/gismo; bash gismo",
|
||||
"bs": "cpl build-start",
|
||||
"pre-build": "cd ../gismo_cli; echo 'gismo-cli:'; cpl build; echo 'gismo:'",
|
||||
"pre-start": "if [ -z $GISMO_ENVIRONMENT ]; then echo '!WARNING! You should start with the right environment!\nRun cpl start-ENV\nSee workspace for more details.'; sleep 2; fi",
|
||||
"pre-dev": "echo 'development:'; ",
|
||||
"dev": "export GISMO_ENVIRONMENT=development; export GISMO_NAME=Gismo-dev; cpl start",
|
||||
"pre-test": "echo 'staging:'; ",
|
||||
"test": "export GISMO_ENVIRONMENT=staging; export GISMO_NAME=Gismo-test; cpl start",
|
||||
"pre-prod": "echo 'production:'; ",
|
||||
"prod": "export GISMO_ENVIRONMENT=production; export GISMO_NAME=Gismo-prod; cpl start"
|
||||
}
|
||||
}
|
||||
}
|
25
src/gismo/__init__.py
Normal file
25
src/gismo/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
40
src/gismo/application.py
Normal file
40
src/gismo/application.py
Normal file
@ -0,0 +1,40 @@
|
||||
from cpl_core.application import ApplicationABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.console import Console
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
from gismo_core.abc.bot_service_abc import BotServiceABC
|
||||
from gismo_core.service.bot_service import BotService
|
||||
from gismo_data.service.migration_service import MigrationService
|
||||
|
||||
|
||||
class Gismo(ApplicationABC):
|
||||
|
||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
ApplicationABC.__init__(self, config, services)
|
||||
|
||||
self._bot: BotService = services.get_service(BotServiceABC)
|
||||
self._logger: LoggerABC = services.get_service(LoggerABC)
|
||||
self._migrations: MigrationService = services.get_service(MigrationService)
|
||||
|
||||
async def configure(self):
|
||||
pass
|
||||
|
||||
async def main(self):
|
||||
try:
|
||||
self._migrations.migrate()
|
||||
self._logger.trace(__name__, f'Try to start {BotService}')
|
||||
await self._bot.start_async()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, 'Start failed', e)
|
||||
|
||||
async def stop_async(self):
|
||||
try:
|
||||
self._logger.trace(__name__, f'Try to stop {BotService}')
|
||||
await self._bot.close()
|
||||
self._logger.trace(__name__, f'Stopped {BotService}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, 'stop failed', e)
|
||||
|
||||
Console.write_line()
|
36
src/gismo/appsettings.example.json
Normal file
36
src/gismo/appsettings.example.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"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": "log_$start_time.log",
|
||||
"ConsoleLogLevel": "ERROR",
|
||||
"FileLogLevel": "WARN"
|
||||
},
|
||||
"Discord": {
|
||||
"Token": ""
|
||||
},
|
||||
"Bot": {
|
||||
"Prefix": "!g",
|
||||
"Servers": [
|
||||
{
|
||||
"Id": "",
|
||||
"LoginMessageChannelId": "",
|
||||
"LoginMessage": "",
|
||||
"MessageDeleteTimer": 0,
|
||||
"WelcomeMessage": "",
|
||||
"GoodbyeMessage": "",
|
||||
"MaxVoiceStateHours": 0,
|
||||
"XpPerMessage": 0,
|
||||
"XpPerOntimeHour": 0,
|
||||
"AFKChannelIds": [],
|
||||
"AdminRoleIds": [],
|
||||
"ModeratorRoleIds": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
14
src/gismo/appsettings.json
Normal file
14
src/gismo/appsettings.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"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": "log_$start_time.log",
|
||||
"ConsoleLogLevel": "ERROR",
|
||||
"FileLogLevel": "WARN"
|
||||
}
|
||||
}
|
24
src/gismo/gismo
Normal file
24
src/gismo/gismo
Normal file
@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
path="`dirname \"$0\"`" # relative
|
||||
path="`( cd \"$path\" && pwd)`" # absolutized and normalized
|
||||
|
||||
cd "$path/../"
|
||||
|
||||
if [[ $1 == "-dev" ]]; then
|
||||
export GISMO_ENVIRONMENT=development
|
||||
export GISMO_NAME=Gismo-dev
|
||||
elif [[ $1 == "-test" ]]; then
|
||||
export GISMO_ENVIRONMENT=staging
|
||||
export GISMO_NAME=Gismo-test
|
||||
elif [[ $1 == "-server" ]]; then
|
||||
export GISMO_ENVIRONMENT=production
|
||||
export GISMO_NAME=Gismo
|
||||
else
|
||||
export GISMO_ENVIRONMENT=production
|
||||
export GISMO_NAME=Gismo-prod
|
||||
fi
|
||||
|
||||
export PYTHONPATH=./:$PYTHONPATH
|
||||
|
||||
python3.9 gismo/main.py
|
56
src/gismo/gismo.json
Normal file
56
src/gismo/gismo.json
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "gismo",
|
||||
"Version": {
|
||||
"Major": "0",
|
||||
"Minor": "3",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
"Description": "sh-edraft Gismo",
|
||||
"LongDescription": "sh-edraft Dicord bot Gismo",
|
||||
"URL": "https://www.sh-edraft.de",
|
||||
"CopyrightDate": "2021 - 2022",
|
||||
"CopyrightName": "sh-edraft.de",
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"sh_cpl-core>=2021.11.0",
|
||||
"sh_cpl-query>=2021.11.0",
|
||||
"discord.py==1.7.3"
|
||||
],
|
||||
"PythonVersion": ">=3.9.2",
|
||||
"PythonPath": {
|
||||
"linux": "../../venv/bin/python"
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "console",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "gismo.main",
|
||||
"EntryPoint": "gismo",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {
|
||||
"cpl_cli": [
|
||||
"*.json"
|
||||
]
|
||||
},
|
||||
"ProjectReferences": [
|
||||
"../gismo_core/gismo-core.json",
|
||||
"../gismo_data/gismo-data.json",
|
||||
"../modules_core/modules-core.json",
|
||||
"../modules/boot_log/boot-log.json",
|
||||
"../modules/base/base.json",
|
||||
"../modules/database/database.json"
|
||||
]
|
||||
}
|
||||
}
|
45
src/gismo/main.py
Normal file
45
src/gismo/main.py
Normal file
@ -0,0 +1,45 @@
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.application import ApplicationBuilder
|
||||
|
||||
from gismo.application import Gismo
|
||||
from gismo.startup import Startup
|
||||
from modules.boot_log.boot_log_extension import BootLogExtension
|
||||
from modules.database.database_extension import DatabaseExtension
|
||||
|
||||
|
||||
class Main:
|
||||
|
||||
def __init__(self):
|
||||
self._gismo: Optional[Gismo] = None
|
||||
|
||||
async def main(self):
|
||||
app_builder = ApplicationBuilder(Gismo)
|
||||
app_builder.use_extension(DatabaseExtension)
|
||||
app_builder.use_extension(BootLogExtension)
|
||||
app_builder.use_startup(Startup)
|
||||
self._gismo: Gismo = await app_builder.build_async()
|
||||
await self._gismo.run_async()
|
||||
|
||||
async def stop(self):
|
||||
await self._gismo.stop_async()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main = Main()
|
||||
ml = asyncio.get_event_loop()
|
||||
try:
|
||||
ml.run_until_complete(main.main())
|
||||
except KeyboardInterrupt:
|
||||
ml.run_until_complete(main.stop())
|
||||
|
||||
# ((
|
||||
# ( `)
|
||||
# ; / ,
|
||||
# / \/
|
||||
# / |
|
||||
# / ~/
|
||||
# / ) ) ~ edraft
|
||||
# ___// | /
|
||||
# `--' \_~-,
|
104
src/gismo/startup.py
Normal file
104
src/gismo/startup.py
Normal file
@ -0,0 +1,104 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.application import StartupABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database import DatabaseSettings
|
||||
from cpl_core.dependency_injection import (ServiceCollectionABC,
|
||||
ServiceProviderABC)
|
||||
from cpl_core.environment import ApplicationEnvironment
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
from gismo_core.abc.bot_service_abc import BotServiceABC
|
||||
from gismo_core.abc.message_service_abc import MessageServiceABC
|
||||
from gismo_core.service.bot_service import BotService
|
||||
from gismo_core.service.message_service import MessageService
|
||||
from gismo_data.abc.known_user_repository_abc import KnownUserRepositoryABC
|
||||
from gismo_data.abc.migration_abc import MigrationABC
|
||||
from gismo_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from gismo_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
|
||||
from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from gismo_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from gismo_data.db_context import DBContext
|
||||
from gismo_data.migration.initial_migration import InitialMigration
|
||||
from gismo_data.migration.migration_0_3 import Migration_0_3
|
||||
from gismo_data.migration.migration_0_3_1 import Migration_0_3_1
|
||||
from gismo_data.service.client_repository_service import (
|
||||
ClientRepositoryABC, ClientRepositoryService)
|
||||
from gismo_data.service.known_user_repository_service import \
|
||||
KnownUserRepositoryService
|
||||
from gismo_data.service.migration_service import MigrationService
|
||||
from gismo_data.service.server_repository_service import \
|
||||
ServerRepositoryService
|
||||
from gismo_data.service.user_joined_server_repository_service import UserJoinedServerRepositoryService
|
||||
from gismo_data.service.user_joined_voice_channel_service import UserJoinedVoiceChannelRepositoryService
|
||||
from gismo_data.service.user_repository_service import UserRepositoryService
|
||||
from modules.base.base import Base
|
||||
from modules.boot_log.boot_log import BootLog
|
||||
from modules.database.database import Database
|
||||
from modules_core.abc.module_abc import ModuleABC
|
||||
from modules_core.abc.module_service_abc import ModuleServiceABC
|
||||
from modules_core.service.module_service import ModuleService
|
||||
|
||||
|
||||
class Startup(StartupABC):
|
||||
|
||||
def __init__(self):
|
||||
StartupABC.__init__(self)
|
||||
self._start_time = datetime.now()
|
||||
|
||||
self._config: Optional[ConfigurationABC] = None
|
||||
|
||||
async def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
||||
environment.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
||||
configuration.add_environment_variables('GISMO_')
|
||||
|
||||
configuration.add_json_file(f'appsettings.json', optional=False)
|
||||
configuration.add_json_file(f'appsettings.{environment.environment_name}.json', optional=True)
|
||||
configuration.add_json_file(f'appsettings.{environment.host_name}.json', optional=True)
|
||||
|
||||
configuration.add_configuration('Startup_StartTime', self._start_time)
|
||||
|
||||
self._config = configuration
|
||||
return configuration
|
||||
|
||||
async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
||||
services.add_logging()
|
||||
|
||||
services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings))
|
||||
|
||||
# modules
|
||||
services.add_singleton(ModuleServiceABC, ModuleService)
|
||||
services.add_singleton(BotServiceABC, BotService)
|
||||
services.add_transient(MessageServiceABC, MessageService)
|
||||
|
||||
# services
|
||||
services.add_transient(MigrationService)
|
||||
|
||||
# data services
|
||||
services.add_transient(ServerRepositoryABC, ServerRepositoryService)
|
||||
services.add_transient(UserRepositoryABC, UserRepositoryService)
|
||||
services.add_transient(ClientRepositoryABC, ClientRepositoryService)
|
||||
services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService)
|
||||
services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService)
|
||||
services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService)
|
||||
|
||||
# modules
|
||||
services.add_transient(ModuleABC, Database)
|
||||
services.add_transient(ModuleABC, Base)
|
||||
services.add_transient(ModuleABC, BootLog)
|
||||
|
||||
# migrations
|
||||
services.add_transient(MigrationABC, InitialMigration)
|
||||
services.add_transient(MigrationABC, Migration_0_3)
|
||||
services.add_transient(MigrationABC, Migration_0_3_1)
|
||||
|
||||
provider: ServiceProviderABC = services.build_service_provider()
|
||||
|
||||
startup_init_time = round((datetime.now() - self._config.get_configuration('Startup_StartTime')).total_seconds(), 2)
|
||||
self._config.add_configuration('Startup_InitTime', startup_init_time)
|
||||
logger: LoggerABC = provider.get_service(LoggerABC)
|
||||
logger.debug(__name__, f'Startup Init time: {startup_init_time}s')
|
||||
|
||||
return provider
|
25
src/gismo_cli/__init__.py
Normal file
25
src/gismo_cli/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo-cli sh-edraft Gismo - CLI
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo - command line interface
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_cli'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.1.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='1', micro='0')
|
16
src/gismo_cli/application.py
Normal file
16
src/gismo_cli/application.py
Normal file
@ -0,0 +1,16 @@
|
||||
from cpl_core.application import ApplicationABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.console import Console
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
|
||||
|
||||
class Application(ApplicationABC):
|
||||
|
||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
ApplicationABC.__init__(self, config, services)
|
||||
|
||||
async def configure(self):
|
||||
pass
|
||||
|
||||
async def main(self):
|
||||
Console.write_line('Hello World')
|
15
src/gismo_cli/appsettings.json
Normal file
15
src/gismo_cli/appsettings.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"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": "log_$start_time.log",
|
||||
"ConsoleLogLevel": "ERROR",
|
||||
"FileLogLevel": "WARN"
|
||||
}
|
||||
}
|
48
src/gismo_cli/gismo-cli.json
Normal file
48
src/gismo_cli/gismo-cli.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "gismo-cli",
|
||||
"Version": {
|
||||
"Major": "0",
|
||||
"Minor": "1",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
"Description": "sh-edraft Gismo - CLI",
|
||||
"LongDescription": "sh-edraft Dicord bot Gismo - command line interface",
|
||||
"URL": "https://www.sh-edraft.de",
|
||||
"CopyrightDate": "2021 - 2022",
|
||||
"CopyrightName": "sh-edraft.de",
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"sh_cpl-core>=2021.11.0",
|
||||
"sh_cpl-query>=2021.11.0"
|
||||
],
|
||||
"PythonVersion": ">=3.9.2",
|
||||
"PythonPath": {
|
||||
"linux": "../../venv/bin/python"
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "console",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "gismo.main",
|
||||
"EntryPoint": "gismo",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {
|
||||
"cpl_cli": [
|
||||
"*.json"
|
||||
]
|
||||
},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
18
src/gismo_cli/main.py
Normal file
18
src/gismo_cli/main.py
Normal file
@ -0,0 +1,18 @@
|
||||
import asyncio
|
||||
|
||||
from cpl_core.application import ApplicationBuilder
|
||||
|
||||
from gismo_cli.application import Application
|
||||
from gismo_cli.startup import Startup
|
||||
|
||||
|
||||
async def main():
|
||||
app_builder = ApplicationBuilder(Application)
|
||||
app_builder.use_startup(Startup)
|
||||
app: Application = await app_builder.build_async()
|
||||
await app.run_async()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ml = asyncio.get_event_loop()
|
||||
ml.run_until_complete(main())
|
16
src/gismo_cli/startup.py
Normal file
16
src/gismo_cli/startup.py
Normal file
@ -0,0 +1,16 @@
|
||||
from cpl_core.application import StartupABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
|
||||
from cpl_core.environment import ApplicationEnvironment
|
||||
|
||||
|
||||
class Startup(StartupABC):
|
||||
|
||||
def __init__(self):
|
||||
StartupABC.__init__(self)
|
||||
|
||||
async def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironment) -> ConfigurationABC:
|
||||
return configuration
|
||||
|
||||
async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
||||
return services.build_service_provider()
|
25
src/gismo_core/__init__.py
Normal file
25
src/gismo_core/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_core'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
25
src/gismo_core/abc/__init__.py
Normal file
25
src/gismo_core/abc/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_core.abc'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
16
src/gismo_core/abc/bot_service_abc.py
Normal file
16
src/gismo_core/abc/bot_service_abc.py
Normal file
@ -0,0 +1,16 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
|
||||
class BotServiceABC(ABC, commands.Bot):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def start_async(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def stop_async(self): pass
|
27
src/gismo_core/abc/message_service_abc.py
Normal file
27
src/gismo_core/abc/message_service_abc.py
Normal file
@ -0,0 +1,27 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Union
|
||||
|
||||
import discord
|
||||
from cpl_query.extension import List
|
||||
from discord.ext.commands import Context
|
||||
|
||||
|
||||
class MessageServiceABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def delete_messages(self, messages: List[discord.Message]): pass
|
||||
|
||||
@abstractmethod
|
||||
async def delete_message(self, message: discord.Message): pass
|
||||
|
||||
@abstractmethod
|
||||
async def send_channel_message(self, channel: discord.TextChannel, message: str): pass
|
||||
|
||||
@abstractmethod
|
||||
async def send_dm_message(self, message: str, receiver: Union[discord.User, discord.Member]): pass
|
||||
|
||||
@abstractmethod
|
||||
async def send_ctx_msg(self, ctx: Context, message: str, file: discord.File = None): pass
|
25
src/gismo_core/configuration/__init__.py
Normal file
25
src/gismo_core/configuration/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_core.configuration'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
36
src/gismo_core/configuration/bot_settings.py
Normal file
36
src/gismo_core/configuration/bot_settings.py
Normal file
@ -0,0 +1,36 @@
|
||||
import traceback
|
||||
|
||||
from cpl_core.configuration import ConfigurationModelABC
|
||||
from cpl_core.console import Console
|
||||
from cpl_query.extension import List
|
||||
from gismo_core.configuration.server_settings import ServerSettings
|
||||
|
||||
|
||||
class BotSettings(ConfigurationModelABC):
|
||||
|
||||
def __init__(self):
|
||||
ConfigurationModelABC.__init__(self)
|
||||
|
||||
self._prefix: str = ''
|
||||
self._servers: List[ServerSettings] = List()
|
||||
|
||||
@property
|
||||
def prefix(self) -> str:
|
||||
return self._prefix
|
||||
|
||||
@property
|
||||
def servers(self) -> List[ServerSettings]:
|
||||
return self._servers
|
||||
|
||||
def from_dict(self, settings: dict):
|
||||
try:
|
||||
self._prefix = settings['Prefix']
|
||||
servers = List(ServerSettings)
|
||||
for s in settings['Servers']:
|
||||
st = ServerSettings()
|
||||
st.from_dict(s)
|
||||
servers.append(st)
|
||||
self._servers = servers
|
||||
except Exception as e:
|
||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings')
|
||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
23
src/gismo_core/configuration/discord_settings.py
Normal file
23
src/gismo_core/configuration/discord_settings.py
Normal file
@ -0,0 +1,23 @@
|
||||
import traceback
|
||||
|
||||
from cpl_core.configuration import ConfigurationModelABC
|
||||
from cpl_core.console import Console
|
||||
|
||||
|
||||
class DiscordSettings(ConfigurationModelABC):
|
||||
|
||||
def __init__(self):
|
||||
ConfigurationModelABC.__init__(self)
|
||||
|
||||
self._token: str = ''
|
||||
|
||||
@property
|
||||
def token(self) -> str:
|
||||
return self._token
|
||||
|
||||
def from_dict(self, settings: dict):
|
||||
try:
|
||||
self._token = settings['Token']
|
||||
except Exception as e:
|
||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in {self.__name__} settings')
|
||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
100
src/gismo_core/configuration/server_settings.py
Normal file
100
src/gismo_core/configuration/server_settings.py
Normal file
@ -0,0 +1,100 @@
|
||||
import traceback
|
||||
|
||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
||||
from cpl_core.console import Console
|
||||
|
||||
|
||||
class ServerSettings(ConfigurationModelABC):
|
||||
|
||||
def __init__(self):
|
||||
ConfigurationModelABC.__init__(self)
|
||||
|
||||
self._id: int = 0
|
||||
self._message_delete_timer: int = 0
|
||||
self._login_message_channel_id: int = 0
|
||||
self._login_message: str = ''
|
||||
self._welcome_message: str = ''
|
||||
self._welcome_message_for_team: str = ''
|
||||
self._goodbye_message: str = ''
|
||||
self._max_voice_state_hours: int = 0
|
||||
self._xp_per_message: int = 0
|
||||
self._xp_per_ontime_hour: int = 0
|
||||
self._afk_channel_ids: list[int] = []
|
||||
self._admin_roles: list[int] = []
|
||||
self._moderator_roles: list[int] = []
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def message_delete_timer(self) -> int:
|
||||
return self._message_delete_timer
|
||||
|
||||
@property
|
||||
def login_message_channel_id(self) -> int:
|
||||
return self._login_message_channel_id
|
||||
|
||||
@property
|
||||
def login_message(self) -> str:
|
||||
return self._login_message
|
||||
|
||||
@property
|
||||
def welcome_message(self) -> str:
|
||||
return self._welcome_message
|
||||
|
||||
@property
|
||||
def welcome_message_for_team(self) -> str:
|
||||
return self._welcome_message_for_team
|
||||
|
||||
@property
|
||||
def goodbye_message(self) -> str:
|
||||
return self._goodbye_message
|
||||
|
||||
@property
|
||||
def max_voice_state_hours(self) -> int:
|
||||
return self._max_voice_state_hours
|
||||
|
||||
@property
|
||||
def xp_per_message(self) -> int:
|
||||
return self._xp_per_message
|
||||
|
||||
@property
|
||||
def xp_per_ontime_hour(self) -> int:
|
||||
return self._xp_per_ontime_hour
|
||||
|
||||
@property
|
||||
def afk_channel_ids(self) -> list[int]:
|
||||
return self._afk_channel_ids
|
||||
|
||||
@property
|
||||
def admin_roles(self) -> list[int]:
|
||||
return self._admin_roles
|
||||
|
||||
@property
|
||||
def moderator_roles(self) -> list[int]:
|
||||
return self._moderator_roles
|
||||
|
||||
def from_dict(self, settings: dict):
|
||||
try:
|
||||
self._id = int(settings['Id'])
|
||||
self._message_delete_timer = int(settings['MessageDeleteTimer'])
|
||||
self._login_message_channel_id = int(settings['LoginMessageChannelId'])
|
||||
self._login_message = settings['LoginMessage']
|
||||
self._welcome_message = settings['WelcomeMessage']
|
||||
self._welcome_message_for_team = settings['WelcomeMessageForTeam']
|
||||
self._goodbye_message = settings['GoodbyeMessage']
|
||||
self._max_voice_state_hours = int(settings['MaxVoiceStateHours'])
|
||||
self._xp_per_message = int(settings['XpPerMessage'])
|
||||
self._xp_per_ontime_hour = int(settings['XpPerOntimeHour'])
|
||||
for id in settings['AFKChannelIds']:
|
||||
self._afk_channel_ids.append(int(id))
|
||||
|
||||
for id in settings['AdminRoleIds']:
|
||||
self._admin_roles.append(int(id))
|
||||
|
||||
for id in settings['ModeratorRoleIds']:
|
||||
self._moderator_roles.append(int(id))
|
||||
except Exception as e:
|
||||
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings')
|
||||
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')
|
44
src/gismo_core/gismo-core.json
Normal file
44
src/gismo_core/gismo-core.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "gismo-core",
|
||||
"Version": {
|
||||
"Major": "0",
|
||||
"Minor": "1",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
"Description": "sh-edraft Gismo - core",
|
||||
"LongDescription": "sh-edraft Dicord bot Gismo - core library",
|
||||
"URL": "https://www.sh-edraft.de",
|
||||
"CopyrightDate": "2021 - 2022",
|
||||
"CopyrightName": "sh-edraft.de",
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"sh_cpl-core>=2021.11.0",
|
||||
"sh_cpl-query>=2021.11.0"
|
||||
],
|
||||
"PythonVersion": ">=3.9.2",
|
||||
"PythonPath": {
|
||||
"linux": "../../venv/bin/python"
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "library",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "",
|
||||
"EntryPoint": "",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
25
src/gismo_core/service/__init__.py
Normal file
25
src/gismo_core/service/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_core.service'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
71
src/gismo_core/service/bot_service.py
Normal file
71
src/gismo_core/service/bot_service.py
Normal file
@ -0,0 +1,71 @@
|
||||
import discord
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.console import Console
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
from cpl_core.logging import LoggerABC, LoggingLevelEnum, LoggingSettings
|
||||
from discord.ext import commands
|
||||
from gismo_core.abc.bot_service_abc import BotServiceABC
|
||||
from gismo_core.configuration.bot_settings import BotSettings
|
||||
from gismo_core.configuration.discord_settings import DiscordSettings
|
||||
from gismo_core.configuration.server_settings import ServerSettings
|
||||
from modules_core.abc.module_service_abc import ModuleServiceABC
|
||||
from modules_core.service.module_service import ModuleService
|
||||
|
||||
|
||||
class BotService(BotServiceABC, commands.Bot):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
logger: LoggerABC,
|
||||
modules: ModuleService,
|
||||
discord_settings: DiscordSettings,
|
||||
bot_settings: BotSettings,
|
||||
env: ApplicationEnvironmentABC,
|
||||
logging_st: LoggingSettings,
|
||||
):
|
||||
# services
|
||||
self._config = config
|
||||
self._logger = logger
|
||||
self._modules = modules
|
||||
self._env = env
|
||||
self._logging_st = logging_st
|
||||
|
||||
# settings
|
||||
self._discord_settings = discord_settings
|
||||
self._bot_settings: BotSettings = bot_settings
|
||||
|
||||
# setup super
|
||||
commands.Bot.__init__(self, command_prefix=bot_settings.prefix, help_command=None, intents=discord.Intents().all())
|
||||
|
||||
async def start_async(self):
|
||||
self._logger.trace(__name__, 'Try to connect to discord')
|
||||
|
||||
self.add_cog(self._modules)
|
||||
|
||||
await self.start(self._discord_settings.token)
|
||||
# continue at on_ready
|
||||
|
||||
async def stop_async(self):
|
||||
self._logger.debug(__name__, f'Try to stop {BotService}')
|
||||
try:
|
||||
pass
|
||||
# save data
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, 'Stop failed', e)
|
||||
|
||||
async def on_ready(self):
|
||||
self._logger.info(__name__, 'Connected to discord')
|
||||
|
||||
self._logger.debug(__name__, 'Try to load discord server configs')
|
||||
for server in self._bot_settings.servers:
|
||||
server: ServerSettings = server
|
||||
self._logger.trace(__name__, f'Try to load config for server: {server.id}')
|
||||
self._config.add_configuration(f'DSERVER_{server.id}', server)
|
||||
self._logger.trace(__name__, f'Loaded config for server: {server.id}')
|
||||
|
||||
self._logger.header(f'{self.user.name}:')
|
||||
if self._logging_st.console.value >= LoggingLevelEnum.INFO.value:
|
||||
Console.banner(self._env.application_name if self._env.application_name != '' else 'Gismo')
|
||||
|
||||
await self._modules.on_ready()
|
89
src/gismo_core/service/message_service.py
Normal file
89
src/gismo_core/service/message_service.py
Normal file
@ -0,0 +1,89 @@
|
||||
import asyncio
|
||||
from typing import Union
|
||||
|
||||
import discord
|
||||
from cpl_core.configuration.configuration_abc import ConfigurationABC
|
||||
from cpl_core.database.context.database_context_abc import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_query.extension import List
|
||||
from discord.ext.commands import Context
|
||||
|
||||
from gismo_core.abc.bot_service_abc import BotServiceABC
|
||||
from gismo_core.abc.message_service_abc import MessageServiceABC
|
||||
from gismo_core.configuration.server_settings import ServerSettings
|
||||
from gismo_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
|
||||
|
||||
class MessageService(MessageServiceABC):
|
||||
|
||||
def __init__(self, config: ConfigurationABC, logger: LoggerABC, bot: BotServiceABC, clients: ClientRepositoryABC, db: DatabaseContextABC):
|
||||
self._config = config
|
||||
self._logger = logger
|
||||
self._bot = bot
|
||||
self._clients = clients
|
||||
self._db = db
|
||||
|
||||
async def delete_messages(self, messages: List[discord.Message]):
|
||||
self._logger.debug(__name__, f'Try to delete {messages.count()} messages')
|
||||
for message in messages:
|
||||
await self.delete_message(message)
|
||||
self._logger.debug(__name__, 'Deleting messages finished')
|
||||
|
||||
async def delete_message(self, message: discord.Message):
|
||||
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{message.guild.id}')
|
||||
await asyncio.sleep(server_st.message_delete_timer)
|
||||
self._logger.debug(__name__, f'Try to delete message:\n\t{message}\n\t{message.content}')
|
||||
guild_id = message.guild.id
|
||||
try:
|
||||
await message.delete()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Deleting message failed', e)
|
||||
else:
|
||||
self._clients.apppend_deleted_message_count(self._bot.user.id, guild_id, 1)
|
||||
self._db.save_changes()
|
||||
self._logger.info(__name__, f'Deleted message {message}')
|
||||
|
||||
async def send_channel_message(self, channel: discord.TextChannel, message: str):
|
||||
self._logger.debug(__name__, f'Try to send message\n\t{message}\n\tto: {channel}')
|
||||
msg = None
|
||||
try:
|
||||
msg = await channel.send(message)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Send message to channel {channel.id} failed', e)
|
||||
else:
|
||||
self._logger.info(__name__, f'Sent message to channel {channel.id}')
|
||||
self._clients.apppend_sent_message_count(self._bot.user.id, channel.guild.id, 1)
|
||||
self._db.save_changes()
|
||||
await self.delete_message(msg)
|
||||
|
||||
async def send_dm_message(self, message: str, receiver: Union[discord.User, discord.Member]):
|
||||
self._logger.debug(__name__, f'Try to send message\n\t{message}\n\tto: {receiver}')
|
||||
try:
|
||||
await receiver.send(message)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Send message to user {receiver.id} failed', e)
|
||||
else:
|
||||
self._clients.apppend_sent_message_count(self._bot.user.id, receiver.guild.id, 1)
|
||||
self._db.save_changes()
|
||||
self._logger.info(__name__, f'Sent message to user {receiver.id}')
|
||||
|
||||
async def send_ctx_msg(self, ctx: Context, message: Union[str, discord.File]):
|
||||
if ctx is None:
|
||||
self._logger.warn(__name__, 'Message context is empty')
|
||||
self._logger.debug(__name__, f'Message: {message}')
|
||||
return
|
||||
|
||||
self._logger.debug(__name__, f'Try to send message\t\t{message}\n\tto: {ctx.channel}')
|
||||
msg = None
|
||||
try:
|
||||
if isinstance(message, discord.File):
|
||||
msg = await ctx.send(file=message)
|
||||
else:
|
||||
msg = await ctx.send(message)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Send message to channel {ctx.channel.id} failed', e)
|
||||
else:
|
||||
self._logger.info(__name__, f'Sent message to channel {ctx.channel.id}')
|
||||
self._clients.apppend_sent_message_count(self._bot.user.id, ctx.guild.id, 1)
|
||||
self._db.save_changes()
|
||||
await self.delete_message(msg)
|
25
src/gismo_data/__init__.py
Normal file
25
src/gismo_data/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_data'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
25
src/gismo_data/abc/__init__.py
Normal file
25
src/gismo_data/abc/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_data.abc'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
53
src/gismo_data/abc/client_repository_abc.py
Normal file
53
src/gismo_data/abc/client_repository_abc.py
Normal file
@ -0,0 +1,53 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from cpl_query.extension import List
|
||||
from gismo_data.model.client import Client
|
||||
|
||||
|
||||
class ClientRepositoryABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def get_clients(self) -> List[Client]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_client_by_id(self, id: int) -> Client: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_client_by_discord_id(self, discord_id: int) -> Client: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_client_by_server_id(self, server_id: int) -> Optional[Client]: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_client_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[Client]: pass
|
||||
|
||||
@abstractmethod
|
||||
def add_client(self, client: Client): pass
|
||||
|
||||
@abstractmethod
|
||||
def update_client(self, client: Client): pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_client(self, client: Client): pass
|
||||
|
||||
@abstractmethod
|
||||
def apppend_sent_message_count(self, id: int, server_id: int, value: int): pass
|
||||
|
||||
@abstractmethod
|
||||
def apppend_received_message_count(self, id: int, server_id: int, value: int): pass
|
||||
|
||||
@abstractmethod
|
||||
def apppend_deleted_message_count(self, id: int, server_id: int, value: int): pass
|
||||
|
||||
@abstractmethod
|
||||
def apppend_received_command_count(self, id: int, server_id: int, value: int): pass
|
||||
|
||||
@abstractmethod
|
||||
def apppend_moved_users_count(self, id: int, server_id: int, value: int): pass
|
30
src/gismo_data/abc/known_user_repository_abc.py
Normal file
30
src/gismo_data/abc/known_user_repository_abc.py
Normal file
@ -0,0 +1,30 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from cpl_query.extension import List
|
||||
|
||||
from gismo_data.model.known_user import KnownUser
|
||||
|
||||
|
||||
class KnownUserRepositoryABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def get_users(self) -> List[KnownUser]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_by_id(self, id: int) -> KnownUser: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_by_discord_id(self, discord_id: int) -> KnownUser: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_user_by_discord_id(self, discord_id: int) -> Optional[KnownUser]: pass
|
||||
|
||||
@abstractmethod
|
||||
def add_user(self, known_user: KnownUser): pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_user(self, known_user: KnownUser): pass
|
13
src/gismo_data/abc/migration_abc.py
Normal file
13
src/gismo_data/abc/migration_abc.py
Normal file
@ -0,0 +1,13 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class MigrationABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def upgrade(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def downgrade(self): pass
|
33
src/gismo_data/abc/server_repository_abc.py
Normal file
33
src/gismo_data/abc/server_repository_abc.py
Normal file
@ -0,0 +1,33 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from cpl_query.extension import List
|
||||
|
||||
from gismo_data.model.server import Server
|
||||
|
||||
|
||||
class ServerRepositoryABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def get_servers(self) -> List[Server]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_server_by_id(self, id: int) -> Server: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_server_by_discord_id(self, discord_id: int) -> Server: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]: pass
|
||||
|
||||
@abstractmethod
|
||||
def add_server(self, server: Server): pass
|
||||
|
||||
@abstractmethod
|
||||
def update_server(self, server: Server): pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_server(self, server: Server): pass
|
35
src/gismo_data/abc/user_joined_server_repository_abc.py
Normal file
35
src/gismo_data/abc/user_joined_server_repository_abc.py
Normal file
@ -0,0 +1,35 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from cpl_query.extension import List
|
||||
from gismo_data.model.user_joined_server import UserJoinedServer
|
||||
|
||||
|
||||
class UserJoinedServerRepositoryABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_joined_servers(self) -> List[UserJoinedServer]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_joined_servers_by_user_id(self, user_id: int) -> list[UserJoinedServer]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_active_user_joined_server_by_user_id(self, user_id: int) -> UserJoinedServer: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_active_user_joined_server_by_user_id(self, user_id: int) -> Optional[UserJoinedServer]: pass
|
||||
|
||||
@abstractmethod
|
||||
def add_user_joined_server(self, user_joined_server: UserJoinedServer): pass
|
||||
|
||||
@abstractmethod
|
||||
def update_user_joined_server(self, user_joined_server: UserJoinedServer): pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_user_joined_server(self, user_joined_server: UserJoinedServer): pass
|
34
src/gismo_data/abc/user_joined_voice_channel_abc.py
Normal file
34
src/gismo_data/abc/user_joined_voice_channel_abc.py
Normal file
@ -0,0 +1,34 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from cpl_query.extension import List
|
||||
from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
|
||||
|
||||
class UserJoinedVoiceChannelRepositoryABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_joined_voice_channels(self) -> List[UserJoinedVoiceChannel]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_joined_voice_channel_by_id(self, id: int) -> UserJoinedVoiceChannel: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_joined_voice_channels_by_user_id(self, user_id: int) -> list[UserJoinedVoiceChannel]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> UserJoinedVoiceChannel: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> Optional[UserJoinedVoiceChannel]: pass
|
||||
|
||||
@abstractmethod
|
||||
def add_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass
|
||||
|
||||
@abstractmethod
|
||||
def update_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass
|
36
src/gismo_data/abc/user_repository_abc.py
Normal file
36
src/gismo_data/abc/user_repository_abc.py
Normal file
@ -0,0 +1,36 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from cpl_query.extension import List
|
||||
|
||||
from gismo_data.model.user import User
|
||||
|
||||
|
||||
class UserRepositoryABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def get_users(self) -> List[User]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_by_id(self, id: int) -> User: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_users_by_discord_id(self, discord_id: int) -> List[User]: pass
|
||||
|
||||
@abstractmethod
|
||||
def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: pass
|
||||
|
||||
@abstractmethod
|
||||
def find_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[User]: pass
|
||||
|
||||
@abstractmethod
|
||||
def add_user(self, user: User): pass
|
||||
|
||||
@abstractmethod
|
||||
def update_user(self, user: User): pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_user(self, user: User): pass
|
34
src/gismo_data/db_context.py
Normal file
34
src/gismo_data/db_context.py
Normal file
@ -0,0 +1,34 @@
|
||||
from cpl_core.database import DatabaseSettings
|
||||
from cpl_core.database.context import DatabaseContext
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
|
||||
class DBContext(DatabaseContext):
|
||||
|
||||
def __init__(self, logger: LoggerABC):
|
||||
|
||||
self._logger = logger
|
||||
|
||||
DatabaseContext.__init__(self)
|
||||
|
||||
|
||||
def connect(self, database_settings: DatabaseSettings):
|
||||
try:
|
||||
self._logger.debug(__name__, "Connecting to database")
|
||||
self._db.connect(database_settings)
|
||||
|
||||
self.save_changes()
|
||||
self._logger.info(__name__, "Connected to database")
|
||||
except Exception as e:
|
||||
self._logger.fatal(__name__, "Connecting to database failed", e)
|
||||
|
||||
def save_changes(self):
|
||||
try:
|
||||
self._logger.trace(__name__, "Save changes")
|
||||
super(DBContext, self).save_changes()
|
||||
self._logger.debug(__name__, "Saved changes")
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, "Saving changes failed", e)
|
||||
|
||||
def select(self, statement: str) -> list[tuple]:
|
||||
return super(DBContext, self).select(statement)
|
44
src/gismo_data/gismo-data.json
Normal file
44
src/gismo_data/gismo-data.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "gismo-data",
|
||||
"Version": {
|
||||
"Major": "0",
|
||||
"Minor": "1",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
"Description": "sh-edraft Gismo - data",
|
||||
"LongDescription": "sh-edraft Dicord bot Gismo - data library",
|
||||
"URL": "https://www.sh-edraft.de",
|
||||
"CopyrightDate": "2021 - 2022",
|
||||
"CopyrightName": "sh-edraft.de",
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"sh_cpl-core>=2021.11.0",
|
||||
"sh_cpl-query>=2021.11.0"
|
||||
],
|
||||
"PythonVersion": ">=3.9.2",
|
||||
"PythonPath": {
|
||||
"linux": "../../venv/bin/python"
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "library",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "",
|
||||
"EntryPoint": "",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
25
src/gismo_data/migration/__init__.py
Normal file
25
src/gismo_data/migration/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_data.migration'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
57
src/gismo_data/migration/initial_migration.py
Normal file
57
src/gismo_data/migration/initial_migration.py
Normal file
@ -0,0 +1,57 @@
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
from gismo_data.abc.migration_abc import MigrationABC
|
||||
from gismo_data.db_context import DBContext
|
||||
|
||||
|
||||
class InitialMigration(MigrationABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db: DBContext):
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
def upgrade(self):
|
||||
self._logger.debug(__name__, 'Running upgrade')
|
||||
|
||||
self._cursor.execute(
|
||||
str(f"""
|
||||
CREATE TABLE IF NOT EXISTS `MigrationHistory` (
|
||||
`MigrationId` VARCHAR(255),
|
||||
`CreatedAt` DATETIME(6),
|
||||
`LastModifiedAt` DATETIME(6),
|
||||
PRIMARY KEY(`MigrationId`)
|
||||
);
|
||||
""")
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(f"""
|
||||
CREATE TABLE IF NOT EXISTS `Servers` (
|
||||
`ServerId` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`DiscordServerId` BIGINT NOT NULL,
|
||||
`CreatedAt` DATETIME(6),
|
||||
`LastModifiedAt` DATETIME(6),
|
||||
PRIMARY KEY(`ServerId`)
|
||||
);
|
||||
""")
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(f"""
|
||||
CREATE TABLE IF NOT EXISTS `Users` (
|
||||
`UserId` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`DiscordId` BIGINT NOT NULL,
|
||||
`XP` BIGINT NOT NULL DEFAULT 0,
|
||||
`ServerId` BIGINT,
|
||||
`CreatedAt` DATETIME(6),
|
||||
`LastModifiedAt` DATETIME(6),
|
||||
FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`),
|
||||
PRIMARY KEY(`UserId`)
|
||||
);
|
||||
""")
|
||||
)
|
||||
|
||||
def downgrade(self):
|
||||
self._cursor.execute('DROP TABLE `Servers`;')
|
||||
self._cursor.execute('DROP TABLE `Users`;')
|
65
src/gismo_data/migration/migration_0_3.py
Normal file
65
src/gismo_data/migration/migration_0_3.py
Normal file
@ -0,0 +1,65 @@
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
from gismo_data.abc.migration_abc import MigrationABC
|
||||
from gismo_data.db_context import DBContext
|
||||
|
||||
class Migration_0_3(MigrationABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db: DBContext):
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
def upgrade(self):
|
||||
self._logger.debug(__name__, 'Running upgrade')
|
||||
|
||||
self._cursor.execute(
|
||||
str(f"""
|
||||
CREATE TABLE IF NOT EXISTS `Clients` (
|
||||
`ClientId` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`DiscordClientId` BIGINT NOT NULL,
|
||||
`SentMessageCount` BIGINT NOT NULL DEFAULT 0,
|
||||
`ReceivedMessageCount` BIGINT NOT NULL DEFAULT 0,
|
||||
`DeletedMessageCount` BIGINT NOT NULL DEFAULT 0,
|
||||
`ReceivedCommandsCount` BIGINT NOT NULL DEFAULT 0,
|
||||
`MovedUsersCount` BIGINT NOT NULL DEFAULT 0,
|
||||
`ServerId` BIGINT,
|
||||
`CreatedAt` DATETIME(6),
|
||||
`LastModifiedAt` DATETIME(6),
|
||||
FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`),
|
||||
PRIMARY KEY(`ClientId`)
|
||||
);
|
||||
""")
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(f"""
|
||||
CREATE TABLE IF NOT EXISTS `KnownUsers` (
|
||||
`KnownUserId` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`DiscordId` BIGINT NOT NULL,
|
||||
`CreatedAt` DATETIME(6),
|
||||
`LastModifiedAt` DATETIME(6),
|
||||
PRIMARY KEY(`KnownUserId`)
|
||||
);
|
||||
""")
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(f"""
|
||||
CREATE TABLE IF NOT EXISTS `UserJoinedServers` (
|
||||
`JoinId` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`UserId` BIGINT NOT NULL,
|
||||
`JoinedOn` DATETIME(6) NOT NULL,
|
||||
`LeavedOn` DATETIME(6),
|
||||
`CreatedAt` DATETIME(6),
|
||||
`LastModifiedAt` DATETIME(6),
|
||||
FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`),
|
||||
PRIMARY KEY(`JoinId`)
|
||||
);
|
||||
""")
|
||||
)
|
||||
|
||||
def downgrade(self):
|
||||
self._cursor.execute('DROP TABLE `Clients`;')
|
||||
self._cursor.execute('DROP TABLE `KnownUsers`;')
|
||||
self._cursor.execute('DROP TABLE `UserJoinedServers`;')
|
35
src/gismo_data/migration/migration_0_3_1.py
Normal file
35
src/gismo_data/migration/migration_0_3_1.py
Normal file
@ -0,0 +1,35 @@
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
from gismo_data.abc.migration_abc import MigrationABC
|
||||
from gismo_data.db_context import DBContext
|
||||
|
||||
class Migration_0_3_1(MigrationABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db: DBContext):
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
def upgrade(self):
|
||||
self._logger.debug(__name__, 'Running upgrade')
|
||||
|
||||
self._cursor.execute(
|
||||
str(f"""
|
||||
CREATE TABLE IF NOT EXISTS `UserJoinedVoiceChannel` (
|
||||
`JoinId` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`UserId` BIGINT NOT NULL,
|
||||
`DiscordChannelId` BIGINT NOT NULL,
|
||||
`JoinedOn` DATETIME(6) NOT NULL,
|
||||
`LeavedOn` DATETIME(6),
|
||||
`CreatedAt` DATETIME(6),
|
||||
`LastModifiedAt` DATETIME(6),
|
||||
FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`),
|
||||
PRIMARY KEY(`JoinId`)
|
||||
);
|
||||
""")
|
||||
)
|
||||
|
||||
def downgrade(self):
|
||||
self._logger.debug(__name__, 'Running downgrade')
|
||||
self._cursor.execute('DROP TABLE `UserJoinedVoiceChannel`;')
|
||||
|
25
src/gismo_data/model/__init__.py
Normal file
25
src/gismo_data/model/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_data.model'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
170
src/gismo_data/model/client.py
Normal file
170
src/gismo_data/model/client.py
Normal file
@ -0,0 +1,170 @@
|
||||
from datetime import datetime
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
from gismo_data.model.server import Server
|
||||
|
||||
|
||||
class Client(TableABC):
|
||||
|
||||
def __init__(self,
|
||||
dc_id: int,
|
||||
smc: int,
|
||||
rmc: int,
|
||||
dmc: int,
|
||||
rcc: int,
|
||||
muc: int,
|
||||
server: Server,
|
||||
created_at: datetime = None,
|
||||
modified_at: datetime = None,
|
||||
id=0
|
||||
):
|
||||
self._client_id = id
|
||||
self._discord_client_id = dc_id
|
||||
self._sent_message_count = smc
|
||||
self._received_message_count = rmc
|
||||
self._deleted_message_count = dmc
|
||||
self._received_command_count = rcc
|
||||
self._moved_users_count = muc
|
||||
self._server: Server = server
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@property
|
||||
def client_id(self) -> int:
|
||||
return self._client_id
|
||||
|
||||
@property
|
||||
def discord_id(self) -> int:
|
||||
return self._discord_client_id
|
||||
|
||||
@property
|
||||
def sent_message_count(self) -> int:
|
||||
return self._sent_message_count
|
||||
|
||||
@sent_message_count.setter
|
||||
def sent_message_count(self, value: int):
|
||||
self._modified_at = datetime.now().isoformat()
|
||||
self._sent_message_count = value
|
||||
|
||||
@property
|
||||
def received_message_count(self) -> int:
|
||||
return self._received_message_count
|
||||
|
||||
@received_message_count.setter
|
||||
def received_message_count(self, value: int):
|
||||
self._modified_at = datetime.now().isoformat()
|
||||
self._received_message_count = value
|
||||
|
||||
@property
|
||||
def deleted_message_count(self) -> int:
|
||||
return self._deleted_message_count
|
||||
|
||||
@deleted_message_count.setter
|
||||
def deleted_message_count(self, value: int):
|
||||
self._modified_at = datetime.now().isoformat()
|
||||
self._deleted_message_count = value
|
||||
|
||||
@property
|
||||
def received_command_count(self) -> int:
|
||||
return self._received_command_count
|
||||
|
||||
@received_command_count.setter
|
||||
def received_command_count(self, value: int):
|
||||
self._modified_at = datetime.now().isoformat()
|
||||
self._received_command_count = value
|
||||
|
||||
@property
|
||||
def moved_users_count(self) -> int:
|
||||
return self._moved_users_count
|
||||
|
||||
@moved_users_count.setter
|
||||
def moved_users_count(self, value: int):
|
||||
self._modified_at = datetime.now().isoformat()
|
||||
self._moved_users_count = value
|
||||
|
||||
@property
|
||||
def server(self) -> Server:
|
||||
return self._server
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Clients`;
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Clients`
|
||||
WHERE `ClientId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_discord_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Clients`
|
||||
WHERE `DiscordClientId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_server_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Clients`
|
||||
WHERE `ServerId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_discord_id_and_server_id_string(id: int, server_id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Clients`
|
||||
WHERE `DiscordClientId` = {id}
|
||||
AND `ServerId` = {server_id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(f"""
|
||||
INSERT INTO `Clients` (
|
||||
`DiscordClientId`,
|
||||
`SentMessageCount`,
|
||||
`ReceivedMessageCount`,
|
||||
`DeletedMessageCount`,
|
||||
`ReceivedCommandsCount`,
|
||||
`MovedUsersCount`,
|
||||
`ServerId`,
|
||||
`CreatedAt`,
|
||||
`LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._discord_client_id},
|
||||
{self._sent_message_count},
|
||||
{self._received_message_count},
|
||||
{self._deleted_message_count},
|
||||
{self._received_message_count},
|
||||
{self._moved_users_count},
|
||||
{self._server.server_id},
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(f"""
|
||||
UPDATE `Clients`
|
||||
SET `SentMessageCount` = {self._sent_message_count},
|
||||
`ReceivedMessageCount` = {self._received_message_count},
|
||||
`DeletedMessageCount` = {self._deleted_message_count},
|
||||
`ReceivedCommandsCount` = {self._received_command_count},
|
||||
`MovedUsersCount` = {self._moved_users_count},
|
||||
`LastModifiedAt` = '{self._modified_at}'
|
||||
WHERE `ClientId` = {self._client_id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(f"""
|
||||
DELETE FROM `Clients`
|
||||
WHERE `ClientId` = {self._client_id};
|
||||
""")
|
67
src/gismo_data/model/known_user.py
Normal file
67
src/gismo_data/model/known_user.py
Normal file
@ -0,0 +1,67 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
from gismo_data.model.server import Server
|
||||
|
||||
|
||||
class KnownUser(TableABC):
|
||||
|
||||
def __init__(self, dc_id: int, created_at: datetime = None, modified_at: datetime = None, id=0):
|
||||
self._known_user_id = id
|
||||
self._discord_id = dc_id
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@property
|
||||
def known_user_id(self) -> int:
|
||||
return self._known_user_id
|
||||
|
||||
@property
|
||||
def discord_id(self) -> int:
|
||||
return self._discord_id
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `KnownUsers`;
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `KnownUsers`
|
||||
WHERE `KnownUserId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_discord_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `KnownUsers`
|
||||
WHERE `DiscordId` = {id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(f"""
|
||||
INSERT INTO `KnownUsers` (
|
||||
`DiscordId`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._discord_id},
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return ''
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(f"""
|
||||
DELETE FROM `KnownUsers`
|
||||
WHERE `Id` = {self._known_user_id};
|
||||
""")
|
47
src/gismo_data/model/migration_history.py
Normal file
47
src/gismo_data/model/migration_history.py
Normal file
@ -0,0 +1,47 @@
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
|
||||
class MigrationHistory(TableABC):
|
||||
|
||||
def __init__(self, id: str):
|
||||
self._id = id
|
||||
|
||||
TableABC.__init__(self)
|
||||
|
||||
@property
|
||||
def migration_id(self) -> str:
|
||||
return self._id
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: str) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `MigrationHistory`
|
||||
WHERE `MigrationId` = '{id}';
|
||||
""")
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(f"""
|
||||
INSERT INTO `MigrationHistory` (
|
||||
`MigrationId`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
'{self._id}',
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(f"""
|
||||
UPDATE `MigrationHistory`
|
||||
SET LastModifiedAt` = '{self._modified_at}'
|
||||
WHERE `MigrationId` = '{self._id}';
|
||||
""")
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(f"""
|
||||
DELETE FROM `MigrationHistory`
|
||||
WHERE `MigrationId` = '{self._id}';
|
||||
""")
|
71
src/gismo_data/model/server.py
Normal file
71
src/gismo_data/model/server.py
Normal file
@ -0,0 +1,71 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
|
||||
class Server(TableABC):
|
||||
|
||||
def __init__(self, dc_id: int, created_at: datetime=None, modified_at: datetime=None, id=0):
|
||||
self._server_id = id
|
||||
self._discord_server_id = dc_id
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@property
|
||||
def server_id(self) -> int:
|
||||
return self._server_id
|
||||
|
||||
@property
|
||||
def discord_server_id(self) -> int:
|
||||
return self._discord_server_id
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Servers`;
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Servers`
|
||||
WHERE `ServerId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_discord_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Servers`
|
||||
WHERE `DiscordServerId` = {id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(f"""
|
||||
INSERT INTO `Servers` (
|
||||
`DiscordServerId`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._discord_server_id},
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(f"""
|
||||
UPDATE `Servers`
|
||||
SET `DiscordServerId` = {self._discord_server_id},
|
||||
`LastModifiedAt` = '{self._modified_at}'
|
||||
WHERE `Id` = {self._server_id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(f"""
|
||||
DELETE FROM `Servers`
|
||||
WHERE `Id` = {self._server_id};
|
||||
""")
|
97
src/gismo_data/model/user.py
Normal file
97
src/gismo_data/model/user.py
Normal file
@ -0,0 +1,97 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
from gismo_data.model.server import Server
|
||||
|
||||
|
||||
class User(TableABC):
|
||||
|
||||
def __init__(self, dc_id: int, xp: int, server: Optional[Server], created_at: datetime = None, modified_at: datetime = None, id=0):
|
||||
self._user_id = id
|
||||
self._discord_id = dc_id
|
||||
self._xp = xp
|
||||
self._server = server
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@property
|
||||
def user_id(self) -> int:
|
||||
return self._user_id
|
||||
|
||||
@property
|
||||
def discord_id(self) -> int:
|
||||
return self._discord_id
|
||||
|
||||
@property
|
||||
def xp(self) -> int:
|
||||
return self._xp
|
||||
|
||||
@xp.setter
|
||||
def xp(self, value: int):
|
||||
self._modified_at = datetime.now().isoformat()
|
||||
self._xp = value
|
||||
|
||||
@property
|
||||
def server(self) -> Optional[Server]:
|
||||
return self._server
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Users`;
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Users`
|
||||
WHERE `UserId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_discord_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Users`
|
||||
WHERE `DiscordId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_discord_id_and_server_id_string(dc_id: int, s_id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `Users`
|
||||
WHERE `DiscordId` = {dc_id}
|
||||
AND `ServerId` = {s_id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(f"""
|
||||
INSERT INTO `Users` (
|
||||
`DiscordId`, `XP`, `ServerId`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._discord_id},
|
||||
{self._xp},
|
||||
{self._server.server_id},
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(f"""
|
||||
UPDATE `Users`
|
||||
SET `XP` = {self._xp},
|
||||
`LastModifiedAt` = '{self._modified_at}'
|
||||
WHERE `UserId` = {self._user_id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(f"""
|
||||
DELETE FROM `Users`
|
||||
WHERE `UserId` = {self._user_id};
|
||||
""")
|
116
src/gismo_data/model/user_joined_server.py
Normal file
116
src/gismo_data/model/user_joined_server.py
Normal file
@ -0,0 +1,116 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
from gismo_data.model.user import User
|
||||
from gismo_data.model.server import Server
|
||||
|
||||
|
||||
class UserJoinedServer(TableABC):
|
||||
|
||||
def __init__(self, user: User, joined_on: datetime, leaved_on: datetime=None, created_at: datetime=None, modified_at: datetime=None, id=0):
|
||||
self._join_id = id
|
||||
self._user = user
|
||||
self._joined_on = joined_on
|
||||
self._leaved_on = leaved_on
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@property
|
||||
def join_id(self) -> int:
|
||||
return self._join_id
|
||||
|
||||
@property
|
||||
def user(self) -> User:
|
||||
return self._user
|
||||
|
||||
@property
|
||||
def joined_on(self) -> datetime:
|
||||
return self._joined_on
|
||||
|
||||
@joined_on.setter
|
||||
def joined_on(self, value: datetime):
|
||||
self._modified_at = datetime.now()
|
||||
self.joined_on = value
|
||||
|
||||
@property
|
||||
def leaved_on(self) -> datetime:
|
||||
return self._leaved_on
|
||||
|
||||
@leaved_on.setter
|
||||
def leaved_on(self, value: datetime):
|
||||
self._modified_at = datetime.now()
|
||||
self._leaved_on = value
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedServers`;
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedServers`
|
||||
WHERE `JoinId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_user_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedServers`
|
||||
WHERE `UserId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_active_by_user_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedServers`
|
||||
WHERE `UserId` = {id}
|
||||
AND `LeavedOn` IS NULL;
|
||||
""")
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
if self._leaved_on is not None:
|
||||
return str(f"""
|
||||
INSERT INTO `UserJoinedServers` (
|
||||
`UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._user.user_id},
|
||||
'{self._joined_on}',
|
||||
'{self._leaved_on}',
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
else:
|
||||
return str(f"""
|
||||
INSERT INTO `UserJoinedServers` (
|
||||
`UserId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._user.user_id},
|
||||
'{self._joined_on}',
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(f"""
|
||||
UPDATE `UserJoinedServers`
|
||||
SET `LeavedOn` = '{self._leaved_on}',
|
||||
`LastModifiedAt` = '{self._modified_at}'
|
||||
WHERE `UserId` = {self._user.user_id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(f"""
|
||||
DELETE FROM `UserJoinedServers`
|
||||
WHERE `Id` = {self._join_id};
|
||||
""")
|
121
src/gismo_data/model/user_joined_voice_channel.py
Normal file
121
src/gismo_data/model/user_joined_voice_channel.py
Normal file
@ -0,0 +1,121 @@
|
||||
from datetime import datetime
|
||||
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
from gismo_data.model.user import User
|
||||
|
||||
|
||||
class UserJoinedVoiceChannel(TableABC):
|
||||
|
||||
def __init__(self, user: User, dc_channel_id: int, joined_on: datetime, leaved_on: datetime = None, created_at: datetime = None, modified_at: datetime = None, id=0):
|
||||
self._join_id = id
|
||||
self._dc_channel_id = dc_channel_id
|
||||
self._user = user
|
||||
self._joined_on = joined_on
|
||||
self._leaved_on = leaved_on
|
||||
|
||||
TableABC.__init__(self)
|
||||
self._created_at = created_at if created_at is not None else self._created_at
|
||||
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||
|
||||
@property
|
||||
def join_id(self) -> int:
|
||||
return self._join_id
|
||||
|
||||
@property
|
||||
def dc_channel_id(self) -> int:
|
||||
return self._dc_channel_id
|
||||
|
||||
@property
|
||||
def user(self) -> User:
|
||||
return self._user
|
||||
|
||||
@property
|
||||
def joined_on(self) -> datetime:
|
||||
return self._joined_on
|
||||
|
||||
@joined_on.setter
|
||||
def joined_on(self, value: datetime):
|
||||
self._modified_at = datetime.now()
|
||||
self.joined_on = value
|
||||
|
||||
@property
|
||||
def leaved_on(self) -> datetime:
|
||||
return self._leaved_on
|
||||
|
||||
@leaved_on.setter
|
||||
def leaved_on(self, value: datetime):
|
||||
self._modified_at = datetime.now()
|
||||
self._leaved_on = value
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedVoiceChannel`;
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedVoiceChannel`
|
||||
WHERE `JoinId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_user_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedVoiceChannel`
|
||||
WHERE `UserId` = {id};
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def get_select_active_by_user_id_string(id: int) -> str:
|
||||
return str(f"""
|
||||
SELECT * FROM `UserJoinedVoiceChannel`
|
||||
WHERE `UserId` = {id}
|
||||
AND `LeavedOn` IS NULL;
|
||||
""")
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
if self._leaved_on is not None:
|
||||
return str(f"""
|
||||
INSERT INTO `UserJoinedVoiceChannel` (
|
||||
`UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._user.user_id},
|
||||
{self._dc_channel_id},
|
||||
'{self._joined_on}',
|
||||
'{self._leaved_on}',
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
else:
|
||||
return str(f"""
|
||||
INSERT INTO `UserJoinedVoiceChannel` (
|
||||
`UserId`, `DiscordChannelId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt`
|
||||
) VALUES (
|
||||
{self._user.user_id},
|
||||
{self._dc_channel_id},
|
||||
'{self._joined_on}',
|
||||
'{self._created_at}',
|
||||
'{self._modified_at}'
|
||||
);
|
||||
""")
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(f"""
|
||||
UPDATE `UserJoinedVoiceChannel`
|
||||
SET `LeavedOn` = '{self._leaved_on}',
|
||||
`LastModifiedAt` = '{self._modified_at}'
|
||||
WHERE `JoinId` = {self._join_id};
|
||||
""")
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(f"""
|
||||
DELETE FROM `UserJoinedVoiceChannel`
|
||||
WHERE `JoinId` = {self._join_id};
|
||||
""")
|
25
src/gismo_data/service/__init__.py
Normal file
25
src/gismo_data/service/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'gismo_data.service'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
173
src/gismo_data/service/client_repository_service.py
Normal file
173
src/gismo_data/service/client_repository_service.py
Normal file
@ -0,0 +1,173 @@
|
||||
from typing import Optional
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
from gismo_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
from gismo_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from gismo_data.model.client import Client
|
||||
|
||||
|
||||
class ClientRepositoryService(ClientRepositoryABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
self._servers = servers
|
||||
|
||||
ClientRepositoryABC.__init__(self)
|
||||
|
||||
def get_clients(self) -> List[Client]:
|
||||
clients = List(Client)
|
||||
self._logger.trace(__name__, f'Send SQL command: {Client.get_select_all_string()}')
|
||||
results = self._context.select(Client.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f'Get client with id {result[0]}')
|
||||
clients.append(Client(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
self._servers.get_server_by_id(result[7]),
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return clients
|
||||
|
||||
def get_client_by_id(self, id: int) -> Client:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_id_string(id)}')
|
||||
result = self._context.select(Client.get_select_by_id_string(id))
|
||||
return Client(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
self._servers.get_server_by_id(result[7]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def get_client_by_discord_id(self, discord_id: int) -> Client:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_discord_id_string(discord_id)}')
|
||||
result = self._context.select(Client.get_select_by_discord_id_string(discord_id))[0]
|
||||
return Client(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
self._servers.get_server_by_id(result[7]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_discord_id_string(discord_id)}')
|
||||
result = self._context.select(Client.get_select_by_discord_id_string(discord_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return Client(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
self._servers.get_server_by_id(result[7]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_client_by_server_id(self, discord_id: int) -> Optional[Client]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_server_id_string(discord_id)}')
|
||||
result = self._context.select(Client.get_select_by_server_id_string(discord_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return Client(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
self._servers.get_server_by_id(result[7]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_client_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[Client]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Client.get_select_by_discord_id_and_server_id_string(discord_id, server_id)}')
|
||||
result = self._context.select(Client.get_select_by_discord_id_and_server_id_string(discord_id, server_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return Client(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
result[6],
|
||||
self._servers.get_server_by_id(result[7]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def add_client(self, client: Client):
|
||||
self._logger.trace(__name__, f'Send SQL command: {client.insert_string}')
|
||||
self._context.cursor.execute(client.insert_string)
|
||||
|
||||
def update_client(self, client: Client):
|
||||
self._logger.trace(__name__, f'Send SQL command: {client.udpate_string}')
|
||||
self._context.cursor.execute(client.udpate_string)
|
||||
|
||||
def delete_client(self, client: Client):
|
||||
self._logger.trace(__name__, f'Send SQL command: {client.delete_string}')
|
||||
self._context.cursor.execute(client.delete_string)
|
||||
|
||||
def _get_client_and_server(self, id: int, server_id: int) -> Client:
|
||||
server = self._servers.find_server_by_discord_id(server_id)
|
||||
if server is None:
|
||||
self._logger.warn(__name__, f'Cannot find server by id {server_id}')
|
||||
raise Exception('Value not found')
|
||||
|
||||
client = self.find_client_by_discord_id_and_server_id(id, server.server_id)
|
||||
if client is None:
|
||||
self._logger.warn(__name__, f'Cannot find client by ids {id}@{server.server_id}')
|
||||
raise Exception('Value not found')
|
||||
|
||||
return client
|
||||
|
||||
def apppend_sent_message_count(self, id: int, server_id: int, value: int):
|
||||
client = self._get_client_and_server(id, server_id)
|
||||
client.sent_message_count += value
|
||||
self.update_client(client)
|
||||
|
||||
def apppend_received_message_count(self, id: int, server_id: int, value: int):
|
||||
client = self._get_client_and_server(id, server_id)
|
||||
client.received_message_count += value
|
||||
self.update_client(client)
|
||||
|
||||
def apppend_deleted_message_count(self, id: int, server_id: int, value: int):
|
||||
client = self._get_client_and_server(id, server_id)
|
||||
client.deleted_message_count += value
|
||||
self.update_client(client)
|
||||
|
||||
def apppend_received_command_count(self, id: int, server_id: int, value: int):
|
||||
client = self._get_client_and_server(id, server_id)
|
||||
client.received_command_count += value
|
||||
self.update_client(client)
|
||||
|
||||
def apppend_moved_users_count(self, id: int, server_id: int, value: int):
|
||||
client = self._get_client_and_server(id, server_id)
|
||||
client.moved_users_count += value
|
||||
self.update_client(client)
|
77
src/gismo_data/service/known_user_repository_service.py
Normal file
77
src/gismo_data/service/known_user_repository_service.py
Normal file
@ -0,0 +1,77 @@
|
||||
from typing import Optional
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_query.extension import List
|
||||
from gismo_data.abc.known_user_repository_abc import KnownUserRepositoryABC
|
||||
|
||||
from gismo_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from gismo_data.model.known_user import KnownUser
|
||||
|
||||
|
||||
class KnownUserRepositoryService(KnownUserRepositoryABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
self._servers = servers
|
||||
|
||||
KnownUserRepositoryABC.__init__(self)
|
||||
|
||||
def get_users(self) -> List[KnownUser]:
|
||||
users = List(KnownUser)
|
||||
self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_all_string()}')
|
||||
results = self._context.select(KnownUser.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f'Get known_user with id {result[0]}')
|
||||
users.append(KnownUser(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return users
|
||||
|
||||
def get_user_by_id(self, id: int) -> KnownUser:
|
||||
self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_by_id_string(id)}')
|
||||
result = self._context.select(KnownUser.get_select_by_id_string(id))
|
||||
return KnownUser(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def get_user_by_discord_id(self, discord_id: int) -> KnownUser:
|
||||
self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_by_discord_id_string(discord_id)}')
|
||||
result = self._context.select(KnownUser.get_select_by_discord_id_string(discord_id))[0]
|
||||
return KnownUser(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_user_by_discord_id(self, discord_id: int) -> Optional[KnownUser]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {KnownUser.get_select_by_discord_id_string(discord_id)}')
|
||||
result = self._context.select(KnownUser.get_select_by_discord_id_string(discord_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return KnownUser(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def add_user(self, known_user: KnownUser):
|
||||
self._logger.trace(__name__, f'Send SQL command: {known_user.insert_string}')
|
||||
self._context.cursor.execute(known_user.insert_string)
|
||||
|
||||
def delete_user(self, known_user: KnownUser):
|
||||
self._logger.trace(__name__, f'Send SQL command: {known_user.delete_string}')
|
||||
self._context.cursor.execute(known_user.delete_string)
|
43
src/gismo_data/service/migration_service.py
Normal file
43
src/gismo_data/service/migration_service.py
Normal file
@ -0,0 +1,43 @@
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
from gismo_data.abc.migration_abc import MigrationABC
|
||||
from gismo_data.model.migration_history import MigrationHistory
|
||||
|
||||
|
||||
class MigrationService:
|
||||
|
||||
def __init__(self, logger: LoggerABC, services: ServiceProviderABC, db: DatabaseContextABC):
|
||||
self._logger = logger
|
||||
self._services = services
|
||||
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
self._migrations: list[MigrationABC] = MigrationABC.__subclasses__()
|
||||
|
||||
def migrate(self):
|
||||
self._logger.info(__name__, f"Running Migrations")
|
||||
for migration in self._migrations:
|
||||
migration_id = migration.__name__
|
||||
try:
|
||||
# check if table exists
|
||||
self._cursor.execute("SHOW TABLES LIKE 'MigrationHistory'")
|
||||
result = self._cursor.fetchone()
|
||||
if result:
|
||||
# there is a table named "tableName"
|
||||
self._logger.trace(__name__, f"Running SQL Command: {MigrationHistory.get_select_by_id_string(migration_id)}")
|
||||
migration_from_db: MigrationHistory = self._db.select(MigrationHistory.get_select_by_id_string(migration_id))
|
||||
self._logger.trace(__name__, migration_from_db)
|
||||
if migration_from_db is not None and len(migration_from_db) > 0:
|
||||
continue
|
||||
|
||||
self._logger.debug(__name__, f"Running Migration {migration}")
|
||||
migration_as_service: MigrationABC = self._services.get_service(migration)
|
||||
migration_as_service.upgrade()
|
||||
self._cursor.execute(MigrationHistory(migration_id).insert_string)
|
||||
self._db.save_changes()
|
||||
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get migration with id {migration}', e)
|
71
src/gismo_data/service/server_repository_service.py
Normal file
71
src/gismo_data/service/server_repository_service.py
Normal file
@ -0,0 +1,71 @@
|
||||
from typing import Optional
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
from gismo_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from gismo_data.model.server import Server
|
||||
|
||||
|
||||
class ServerRepositoryService(ServerRepositoryABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
ServerRepositoryABC.__init__(self)
|
||||
|
||||
def get_servers(self) -> List[Server]:
|
||||
servers = List(Server)
|
||||
self._logger.trace(__name__, f'Send SQL command: {Server.get_select_all_string()}')
|
||||
results = self._context.select(Server.get_select_all_string())
|
||||
for result in results:
|
||||
servers.append(Server(
|
||||
result[1],
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return servers
|
||||
|
||||
def get_server_by_id(self, id: int) -> Server:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Server.get_select_by_id_string(id)}')
|
||||
result = self._context.select(Server.get_select_by_id_string(id))[0]
|
||||
return Server(
|
||||
result[1],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def get_server_by_discord_id(self, discord_id: int) -> Server:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}')
|
||||
result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0]
|
||||
return Server(
|
||||
result[1],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}')
|
||||
result = self._context.select(Server.get_select_by_discord_id_string(discord_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return Server(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def add_server(self, server: Server):
|
||||
self._logger.trace(__name__, f'Send SQL command: {server.insert_string}')
|
||||
self._context.cursor.execute(server.insert_string)
|
||||
|
||||
def update_server(self, server: Server):
|
||||
self._logger.trace(__name__, f'Send SQL command: {server.udpate_string}')
|
||||
self._context.cursor.execute(server.udpate_string)
|
||||
|
||||
def delete_server(self, server: Server):
|
||||
self._logger.trace(__name__, f'Send SQL command: {server.delete_string}')
|
||||
self._context.cursor.execute(server.delete_string)
|
107
src/gismo_data/service/user_joined_server_repository_service.py
Normal file
107
src/gismo_data/service/user_joined_server_repository_service.py
Normal file
@ -0,0 +1,107 @@
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_query.extension import List
|
||||
from gismo_data.abc.user_joined_server_repository_abc import \
|
||||
UserJoinedServerRepositoryABC
|
||||
from gismo_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from gismo_data.model.user import User
|
||||
from gismo_data.model.user_joined_server import UserJoinedServer
|
||||
|
||||
|
||||
class UserJoinedServerRepositoryService(UserJoinedServerRepositoryABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, users: UserRepositoryABC):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
self._users = users
|
||||
|
||||
UserJoinedServerRepositoryABC.__init__(self)
|
||||
|
||||
def get_user_joined_servers(self) -> List[UserJoinedServer]:
|
||||
joins = List(UserJoinedServer)
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_all_string()}')
|
||||
results = self._context.select(UserJoinedServer.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f'Get user-joined-server with id {result[0]}')
|
||||
joins.append(UserJoinedServer(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return joins
|
||||
|
||||
def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer:
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_id_string(id)}')
|
||||
result = self._context.select(UserJoinedServer.get_select_by_id_string(id))[0]
|
||||
return UserJoinedServer(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def get_user_joined_servers_by_user_id(self, user_id: int) -> List[UserJoinedServer]:
|
||||
joins = List(UserJoinedServer)
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_user_id_string(user_id)}')
|
||||
results = self._context.select(UserJoinedServer.get_select_by_user_id_string(user_id))
|
||||
for result in results:
|
||||
joins.append(UserJoinedServer(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return joins
|
||||
|
||||
def get_active_user_joined_server_by_user_id(self, user_id: int) -> UserJoinedServer:
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_user_id_string(user_id)}')
|
||||
result = self._context.select(UserJoinedServer.get_select_active_by_user_id_string(user_id))[0]
|
||||
return UserJoinedServer(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_active_user_joined_server_by_user_id(self, user_id: int) -> Optional[UserJoinedServer]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_user_id_string(user_id)}')
|
||||
result = self._context.select(UserJoinedServer.get_select_active_by_user_id_string(user_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return UserJoinedServer(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def add_user_joined_server(self, user_joined_server: UserJoinedServer):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user_joined_server.insert_string}')
|
||||
self._context.cursor.execute(user_joined_server.insert_string)
|
||||
|
||||
def update_user_joined_server(self, user_joined_server: UserJoinedServer):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user_joined_server.udpate_string}')
|
||||
self._context.cursor.execute(user_joined_server.udpate_string)
|
||||
|
||||
def delete_user_joined_server(self, user_joined_server: UserJoinedServer):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user_joined_server.delete_string}')
|
||||
self._context.cursor.execute(user_joined_server.delete_string)
|
107
src/gismo_data/service/user_joined_voice_channel_service.py
Normal file
107
src/gismo_data/service/user_joined_voice_channel_service.py
Normal file
@ -0,0 +1,107 @@
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_query.extension import List
|
||||
from gismo_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from gismo_data.model.user import User
|
||||
from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
|
||||
|
||||
from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
|
||||
|
||||
class UserJoinedVoiceChannelRepositoryService(UserJoinedVoiceChannelRepositoryABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, users: UserRepositoryABC):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
self._users = users
|
||||
|
||||
UserJoinedVoiceChannelRepositoryABC.__init__(self)
|
||||
|
||||
def get_user_joined_voice_channels(self) -> List[UserJoinedVoiceChannel]:
|
||||
joins = List(UserJoinedVoiceChannel)
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_all_string()}')
|
||||
results = self._context.select(UserJoinedVoiceChannel.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f'Get user-joined-voice-channel with id {result[0]}')
|
||||
joins.append(UserJoinedVoiceChannel(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return joins
|
||||
|
||||
def get_user_joined_voice_channel_by_id(self, id: int) -> UserJoinedVoiceChannel:
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_id_string(id)}')
|
||||
result = self._context.select(UserJoinedVoiceChannel.get_select_by_id_string(id))[0]
|
||||
return UserJoinedVoiceChannel(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def get_user_joined_voice_channels_by_user_id(self, user_id: int) -> List[UserJoinedVoiceChannel]:
|
||||
joins = List(UserJoinedVoiceChannel)
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}')
|
||||
results = self._context.select(UserJoinedVoiceChannel.get_select_by_user_id_string(user_id))
|
||||
for result in results:
|
||||
joins.append(UserJoinedVoiceChannel(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return joins
|
||||
|
||||
def get_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> UserJoinedVoiceChannel:
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}')
|
||||
result = self._context.select(UserJoinedVoiceChannel.get_select_active_by_user_id_string(user_id))[0]
|
||||
return UserJoinedVoiceChannel(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> Optional[UserJoinedVoiceChannel]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}')
|
||||
result = self._context.select(UserJoinedVoiceChannel.get_select_active_by_user_id_string(user_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return UserJoinedVoiceChannel(
|
||||
self._users.get_user_by_id(result[1]),
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
result[5],
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def add_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.insert_string}')
|
||||
self._context.cursor.execute(user_joined_voice_channel.insert_string)
|
||||
|
||||
def update_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.udpate_string}')
|
||||
self._context.cursor.execute(user_joined_voice_channel.udpate_string)
|
||||
|
||||
def delete_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.delete_string}')
|
||||
self._context.cursor.execute(user_joined_voice_channel.delete_string)
|
97
src/gismo_data/service/user_repository_service.py
Normal file
97
src/gismo_data/service/user_repository_service.py
Normal file
@ -0,0 +1,97 @@
|
||||
from typing import Optional
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
from gismo_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from gismo_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from gismo_data.model.user import User
|
||||
|
||||
|
||||
class UserRepositoryService(UserRepositoryABC):
|
||||
|
||||
def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
self._servers = servers
|
||||
|
||||
UserRepositoryABC.__init__(self)
|
||||
|
||||
def get_users(self) -> List[User]:
|
||||
users = List(User)
|
||||
self._logger.trace(__name__, f'Send SQL command: {User.get_select_all_string()}')
|
||||
results = self._context.select(User.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f'Get user with id {result[0]}')
|
||||
users.append(User(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
return users
|
||||
|
||||
def get_user_by_id(self, id: int) -> User:
|
||||
self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_id_string(id)}')
|
||||
result = self._context.select(User.get_select_by_id_string(id))[0]
|
||||
|
||||
return User(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def get_users_by_discord_id(self, discord_id: int) -> List[User]:
|
||||
users = List(User)
|
||||
self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_string(discord_id)}')
|
||||
results = self._context.select(User.get_select_by_discord_id_string(discord_id))
|
||||
for result in results:
|
||||
users.append(User(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
))
|
||||
|
||||
def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User:
|
||||
self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_and_server_id_string(discord_id, server_id)}')
|
||||
result = self._context.select(User.get_select_by_discord_id_and_server_id_string(discord_id, server_id))[0]
|
||||
|
||||
return User(
|
||||
result[1],
|
||||
result[2],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def find_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[User]:
|
||||
self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_and_server_id_string(discord_id, server_id)}')
|
||||
result = self._context.select(User.get_select_by_discord_id_and_server_id_string(discord_id, server_id))
|
||||
if result is None or len(result) == 0:
|
||||
return None
|
||||
|
||||
result = result[0]
|
||||
|
||||
return User(
|
||||
result[1],
|
||||
result[2],
|
||||
result[3],
|
||||
result[4],
|
||||
self._servers.get_server_by_id(result[3]),
|
||||
id=result[0]
|
||||
)
|
||||
|
||||
def add_user(self, user: User):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user.insert_string}')
|
||||
self._context.cursor.execute(user.insert_string)
|
||||
|
||||
def update_user(self, user: User):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user.udpate_string}')
|
||||
self._context.cursor.execute(user.udpate_string)
|
||||
|
||||
def delete_user(self, user: User):
|
||||
self._logger.trace(__name__, f'Send SQL command: {user.delete_string}')
|
||||
self._context.cursor.execute(user.delete_string)
|
0
src/modules/__init__.py
Normal file
0
src/modules/__init__.py
Normal file
25
src/modules/base/__init__.py
Normal file
25
src/modules/base/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'modules.base'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
43
src/modules/base/base.json
Normal file
43
src/modules/base/base.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "modules/base",
|
||||
"Version": {
|
||||
"Major": "0",
|
||||
"Minor": "0",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "",
|
||||
"AuthorEmail": "",
|
||||
"Description": "",
|
||||
"LongDescription": "",
|
||||
"URL": "",
|
||||
"CopyrightDate": "",
|
||||
"CopyrightName": "",
|
||||
"LicenseName": "",
|
||||
"LicenseDescription": "",
|
||||
"Dependencies": [
|
||||
"sh_cpl-core>=2021.11.0.post1"
|
||||
],
|
||||
"PythonVersion": ">=3.9.2",
|
||||
"PythonPath": {
|
||||
"linux": ""
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "library",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "modules/base.main",
|
||||
"EntryPoint": "modules/base",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
262
src/modules/base/base.py
Normal file
262
src/modules/base/base.py
Normal file
@ -0,0 +1,262 @@
|
||||
from datetime import datetime
|
||||
from typing import Union
|
||||
|
||||
import discord
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging.logger_abc import LoggerABC
|
||||
|
||||
from gismo_core.abc.bot_service_abc import BotServiceABC
|
||||
from gismo_core.abc.message_service_abc import MessageServiceABC
|
||||
from gismo_core.configuration.server_settings import ServerSettings
|
||||
from gismo_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
from gismo_data.abc.known_user_repository_abc import KnownUserRepositoryABC
|
||||
from gismo_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from gismo_data.abc.user_joined_server_repository_abc import \
|
||||
UserJoinedServerRepositoryABC
|
||||
from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from gismo_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from gismo_data.model.known_user import KnownUser
|
||||
from gismo_data.model.user import User
|
||||
from gismo_data.model.user_joined_server import UserJoinedServer
|
||||
from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
|
||||
from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC
|
||||
from modules_core.abc.events.on_member_remove_abc import OnMemberRemoveABC
|
||||
from modules_core.abc.events.on_message_abc import OnMessageABC
|
||||
from modules_core.abc.events.on_voice_state_update_abc import \
|
||||
OnVoiceStateUpdateABC
|
||||
from modules_core.abc.module_abc import ModuleABC
|
||||
|
||||
|
||||
class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceStateUpdateABC):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
logger: LoggerABC,
|
||||
clients: ClientRepositoryABC,
|
||||
servers: ServerRepositoryABC,
|
||||
known_users: KnownUserRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
user_joins: UserJoinedServerRepositoryABC,
|
||||
user_joins_vc: UserJoinedVoiceChannelRepositoryABC,
|
||||
bot: BotServiceABC,
|
||||
db: DatabaseContextABC,
|
||||
messenger: MessageServiceABC
|
||||
):
|
||||
self._config = config
|
||||
self._logger = logger
|
||||
self._clients = clients
|
||||
self._servers = servers
|
||||
self._known_users = known_users
|
||||
self._users = users
|
||||
self._user_joins = user_joins
|
||||
self._user_joins_vc = user_joins_vc
|
||||
self._bot = bot
|
||||
self._db = db
|
||||
self._messenger = messenger
|
||||
|
||||
ModuleABC.__init__(self)
|
||||
self._priorities[OnMemberJoinABC] = 1
|
||||
self._priorities[OnMemberRemoveABC] = 1
|
||||
self._priorities[OnMessageABC] = 30
|
||||
self._priorities[OnVoiceStateUpdateABC] = 10
|
||||
self._logger.trace(__name__, f'Module {type(self)} loaded')
|
||||
|
||||
def _apppend_received_message_count(self, g_id: int):
|
||||
try:
|
||||
self._clients.apppend_received_message_count(self._bot.user.id, g_id, 1)
|
||||
self._db.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot edit client {self._bot.user.id}@{g_id}')
|
||||
|
||||
def _apppend_deleted_message_count(self, g_id: int):
|
||||
try:
|
||||
self._clients.apppend_received_message_count(self._bot.user.id, g_id, 1)
|
||||
self._db.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot edit client {self._bot.user.id}@{g_id}')
|
||||
|
||||
def _check_for_known_user(self, member: Union[discord.User, discord.Member]):
|
||||
self._logger.debug(__name__, f'Check if user is already known {member}')
|
||||
try:
|
||||
user = self._known_users.find_user_by_discord_id(member.id)
|
||||
if user is not None:
|
||||
return
|
||||
|
||||
self._logger.debug(__name__, f'Add user: {member.id}')
|
||||
self._known_users.add_user(KnownUser(member.id))
|
||||
self._db.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get user {member.id}', e)
|
||||
|
||||
async def _add_if_not_exists_user(self, member: Union[discord.User, discord.Member]):
|
||||
self._logger.debug(__name__, f'Check if user exists {member}')
|
||||
settings: ServerSettings = self._config.get_configuration(f'DSERVER_{member.guild.id}')
|
||||
await self._messenger.send_dm_message(settings.welcome_message.format(member.guild.name), member)
|
||||
|
||||
for roleId in settings.admin_roles:
|
||||
g: discord.Guild = member.guild
|
||||
role: discord.Role = g.get_role(roleId)
|
||||
for admin in role.members:
|
||||
await self._messenger.send_dm_message(settings.welcome_message_for_team.format(member.name), admin)
|
||||
|
||||
for roleId in settings.moderator_roles:
|
||||
g: discord.Guild = member.guild
|
||||
role: discord.Role = g.get_role(roleId)
|
||||
for mod in role.members:
|
||||
await self._messenger.send_dm_message(settings.welcome_message_for_team.format(member.name), mod)
|
||||
|
||||
try:
|
||||
server = self._servers.get_server_by_discord_id(member.guild.id)
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id)
|
||||
if user is not None:
|
||||
self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now()))
|
||||
return
|
||||
|
||||
self._logger.debug(__name__, f'Add user: {member.id}')
|
||||
self._users.add_user(User(member.id, 0, server))
|
||||
self._db.save_changes()
|
||||
user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id)
|
||||
self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now()))
|
||||
self._db.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get user {member.id}', e)
|
||||
|
||||
async def _remove_user(self, member: Union[discord.User, discord.Member]):
|
||||
self._logger.debug(__name__, f'Remove user {member}')
|
||||
settings: ServerSettings = self._config.get_configuration(f'DSERVER_{member.guild.id}')
|
||||
await self._messenger.send_dm_message(settings.goodbye_message, member)
|
||||
|
||||
try:
|
||||
server = self._servers.get_server_by_discord_id(member.guild.id)
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id)
|
||||
if user is None:
|
||||
self._logger.error(__name__, f'Cannot find user {member}')
|
||||
return
|
||||
|
||||
join = self._user_joins.get_active_user_joined_server_by_user_id(user.user_id)
|
||||
join.leaved_on = datetime.now()
|
||||
self._user_joins.update_user_joined_server(join)
|
||||
self._db.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get user {member.id}', e)
|
||||
|
||||
def _update_voice_state(self, joined: bool, dc_user_id: int, dc_channel_id: int, srv_id: int):
|
||||
user: User = None
|
||||
try:
|
||||
user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, srv_id)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get user {dc_user_id}', e)
|
||||
return
|
||||
|
||||
if user is None:
|
||||
self._logger.error(__name__, f'User not found {dc_user_id}')
|
||||
return
|
||||
|
||||
try:
|
||||
if joined:
|
||||
join = UserJoinedVoiceChannel(user, dc_channel_id, datetime.now())
|
||||
self._user_joins_vc.add_user_joined_voice_channel(join)
|
||||
self._db.save_changes()
|
||||
return
|
||||
|
||||
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{user.server.discord_server_id}')
|
||||
|
||||
join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.user_id)
|
||||
join.leaved_on = datetime.now()
|
||||
|
||||
# ontime as hours
|
||||
ontime = round((join.leaved_on - join.joined_on).total_seconds()/3600, 2)
|
||||
old_xp = user.xp
|
||||
user.xp += round(ontime * server_st.xp_per_ontime_hour)
|
||||
|
||||
self._user_joins_vc.update_user_joined_voice_channel(join)
|
||||
self._users.update_user(user)
|
||||
self._db.save_changes()
|
||||
|
||||
self._logger.debug(__name__, f'User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Ontime validation failed', e)
|
||||
|
||||
def _handle_message_for_xp(self, message: discord.Message):
|
||||
dc_user_id = message.author.id
|
||||
try:
|
||||
server = self._servers.get_server_by_discord_id(message.guild.id)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get server {message.guild.id}', e)
|
||||
return
|
||||
|
||||
user: User = None
|
||||
try:
|
||||
user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get user {dc_user_id}', e)
|
||||
return
|
||||
|
||||
if user is None:
|
||||
self._logger.error(__name__, f'User not found {dc_user_id}')
|
||||
return
|
||||
|
||||
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{user.server.discord_server_id}')
|
||||
old_xp = user.xp
|
||||
user.xp += server_st._xp_per_message
|
||||
self._users.update_user(user)
|
||||
self._db.save_changes()
|
||||
|
||||
self._logger.debug(__name__, f'User {user} sent message. xp: from {old_xp} to {user.xp}')
|
||||
|
||||
async def on_member_join(self, member: Union[discord.User, discord.Member]):
|
||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
||||
self._check_for_known_user(member)
|
||||
await self._add_if_not_exists_user(member)
|
||||
|
||||
async def on_member_remove(self, member: Union[discord.User, discord.Member]):
|
||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
||||
await self._remove_user(member)
|
||||
|
||||
async def on_message(self, message: discord.Message):
|
||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
||||
if message is None or message.guild is None:
|
||||
return
|
||||
self._apppend_received_message_count(message.guild.id)
|
||||
|
||||
if not message.author.bot:
|
||||
self._handle_message_for_xp(message)
|
||||
|
||||
async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState):
|
||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
||||
self._logger.trace(__name__, f'Detected on_voice_state_update {member.id} from {before} to {after}')
|
||||
u: discord.User = member
|
||||
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{member.guild.id}')
|
||||
server = self._servers.get_server_by_discord_id(member.guild.id)
|
||||
|
||||
try:
|
||||
# join
|
||||
if before.channel is None and after.channel is not None and after.channel.id not in server_st.afk_channel_ids:
|
||||
self._logger.trace(__name__, f'User {u.id} joined {after.channel}')
|
||||
self._update_voice_state(True, member.id, after.channel.id, server.server_id)
|
||||
|
||||
# leave
|
||||
elif before.channel is not None and after.channel is None and before.channel.id not in server_st.afk_channel_ids:
|
||||
self._logger.trace(__name__, f'User {u.id} left {before.channel}')
|
||||
self._update_voice_state(False, member.id, before.channel.id, server.server_id)
|
||||
|
||||
# channel to channel
|
||||
elif before.channel is not None and after.channel is not None:
|
||||
# joined
|
||||
if before.channel.id in server_st.afk_channel_ids and after.channel.id not in server_st.afk_channel_ids:
|
||||
self._logger.trace(__name__, f'User {u.id} joined {after.channel}')
|
||||
self._update_voice_state(True, member.id, after.channel.id, server.server_id)
|
||||
|
||||
# left
|
||||
elif after.channel.id in server_st.afk_channel_ids and before.channel.id not in server_st.afk_channel_ids:
|
||||
self._logger.trace(__name__, f'User {u.id} left {before.channel}')
|
||||
self._update_voice_state(False, member.id, before.channel.id, server.server_id)
|
||||
|
||||
else:
|
||||
self._logger.trace(__name__, f'User {u.id} switched to {after.channel}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot handle voice state for user {u.id}', e)
|
25
src/modules/boot_log/__init__.py
Normal file
25
src/modules/boot_log/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'modules.boot_log'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
44
src/modules/boot_log/boot-log.json
Normal file
44
src/modules/boot_log/boot-log.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "modules/boot-log",
|
||||
"Version": {
|
||||
"Major": "0",
|
||||
"Minor": "1",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
"Description": "sh-edraft Gismo - Boot log",
|
||||
"LongDescription": "sh-edraft Dicord bot Gismo - Boot log",
|
||||
"URL": "https://www.sh-edraft.de",
|
||||
"CopyrightDate": "2021 - 2022",
|
||||
"CopyrightName": "sh-edraft.de",
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"sh_cpl-core>=2021.11.0",
|
||||
"sh_cpl-query>=2021.11.0"
|
||||
],
|
||||
"PythonVersion": ">=3.9.2",
|
||||
"PythonPath": {
|
||||
"linux": "../../venv/bin/python"
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "library",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../../dist",
|
||||
"Main": "",
|
||||
"EntryPoint": "",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
72
src/modules/boot_log/boot_log.py
Normal file
72
src/modules/boot_log/boot_log.py
Normal file
@ -0,0 +1,72 @@
|
||||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
from discord import guild
|
||||
|
||||
from gismo_core.abc.bot_service_abc import BotServiceABC
|
||||
from gismo_core.abc.message_service_abc import MessageServiceABC
|
||||
from gismo_core.configuration.server_settings import ServerSettings
|
||||
from modules_core.abc.events.on_ready_abc import OnReadyABC
|
||||
from modules_core.abc.module_abc import ModuleABC
|
||||
|
||||
|
||||
class BootLog(ModuleABC, OnReadyABC):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
logger: LoggerABC,
|
||||
bot: BotServiceABC,
|
||||
message_service: MessageServiceABC
|
||||
):
|
||||
self._config = config
|
||||
|
||||
self._logger = logger
|
||||
self._bot = bot
|
||||
self._message_service = message_service
|
||||
|
||||
ModuleABC.__init__(self)
|
||||
self._priorities[OnReadyABC] = 10
|
||||
self._logger.trace(__name__, f'Module {type(self)} loaded')
|
||||
|
||||
async def on_ready(self):
|
||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
||||
try:
|
||||
start_time = self._config.get_configuration('Bot_StartTime')
|
||||
init_time = round((datetime.now() - start_time).total_seconds(), 2)
|
||||
self._config.add_configuration('InitTime', init_time)
|
||||
self._logger.debug(__name__, f'Bot Init time: {init_time}s')
|
||||
# print warning if initialisation took too long
|
||||
if init_time >= 30:
|
||||
self._logger.warn(
|
||||
__name__, 'It takes long time to start the bot!')
|
||||
|
||||
# print error if initialisation took way too long
|
||||
elif init_time >= 90:
|
||||
self._logger.error(
|
||||
__name__, 'It takes very long time to start the bot!!!')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, 'Init time calculation failed', e)
|
||||
return
|
||||
|
||||
for g in self._bot.guilds:
|
||||
g: guild = g
|
||||
self._logger.debug(__name__, f'Server detected: {g.id}')
|
||||
|
||||
server_settings: ServerSettings = self._config.get_configuration(
|
||||
f'DSERVER_{g.id}')
|
||||
if server_settings is None:
|
||||
self._logger.error(
|
||||
__name__, f'Config for server {g.id} not found!')
|
||||
await self._bot.close()
|
||||
return
|
||||
|
||||
await self._message_service.send_channel_message(
|
||||
self._bot.get_channel(
|
||||
server_settings.login_message_channel_id),
|
||||
server_settings.login_message.format(init_time)
|
||||
)
|
||||
|
||||
self._logger.trace(__name__, f'Module {type(self)} stopped')
|
17
src/modules/boot_log/boot_log_extension.py
Normal file
17
src/modules/boot_log/boot_log_extension.py
Normal file
@ -0,0 +1,17 @@
|
||||
from datetime import datetime
|
||||
|
||||
from cpl_core.application.application_extension_abc import ApplicationExtensionABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
|
||||
class BootLogExtension(ApplicationExtensionABC):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
logger: LoggerABC = services.get_service(LoggerABC)
|
||||
logger.debug(__name__, 'BootLog extension started')
|
||||
config.add_configuration('Bot_StartTime', datetime.now())
|
25
src/modules/database/__init__.py
Normal file
25
src/modules/database/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'modules.database'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
43
src/modules/database/database.json
Normal file
43
src/modules/database/database.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "modules/database",
|
||||
"Version": {
|
||||
"Major": "0",
|
||||
"Minor": "0",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "",
|
||||
"AuthorEmail": "",
|
||||
"Description": "",
|
||||
"LongDescription": "",
|
||||
"URL": "",
|
||||
"CopyrightDate": "",
|
||||
"CopyrightName": "",
|
||||
"LicenseName": "",
|
||||
"LicenseDescription": "",
|
||||
"Dependencies": [
|
||||
"sh_cpl-core>=2021.11.0.post1"
|
||||
],
|
||||
"PythonVersion": ">=3.9.2",
|
||||
"PythonPath": {
|
||||
"linux": ""
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "library",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "modules/database.main",
|
||||
"EntryPoint": "modules/database",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
318
src/modules/database/database.py
Normal file
318
src/modules/database/database.py
Normal file
@ -0,0 +1,318 @@
|
||||
from ctypes import Union
|
||||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
from gismo_core.abc.bot_service_abc import BotServiceABC
|
||||
from gismo_core.configuration.server_settings import ServerSettings
|
||||
from gismo_data.abc.client_repository_abc import ClientRepositoryABC
|
||||
from gismo_data.abc.known_user_repository_abc import KnownUserRepositoryABC
|
||||
from gismo_data.abc.user_joined_server_repository_abc import \
|
||||
UserJoinedServerRepositoryABC
|
||||
from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from gismo_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from gismo_data.model.client import Client
|
||||
from gismo_data.model.known_user import KnownUser
|
||||
from gismo_data.model.server import Server
|
||||
from gismo_data.model.user import User
|
||||
from gismo_data.model.user_joined_server import UserJoinedServer
|
||||
from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
|
||||
from gismo_data.service.user_repository_service import ServerRepositoryABC
|
||||
from modules_core.abc.events.on_ready_abc import OnReadyABC
|
||||
from modules_core.abc.module_abc import ModuleABC
|
||||
|
||||
|
||||
class Database(ModuleABC, OnReadyABC):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
logger: LoggerABC,
|
||||
bot: BotServiceABC,
|
||||
db_context: DatabaseContextABC,
|
||||
server_repo: ServerRepositoryABC,
|
||||
user_repo: UserRepositoryABC,
|
||||
client_repo: ClientRepositoryABC,
|
||||
known_users: KnownUserRepositoryABC,
|
||||
user_joins: UserJoinedServerRepositoryABC,
|
||||
user_joins_vc: UserJoinedVoiceChannelRepositoryABC
|
||||
):
|
||||
self._config = config
|
||||
|
||||
self._logger = logger
|
||||
self._bot = bot
|
||||
self._db_context = db_context
|
||||
self._servers = server_repo
|
||||
self._users = user_repo
|
||||
self._clients = client_repo
|
||||
self._known_users = known_users
|
||||
self._user_joins = user_joins
|
||||
self._user_joins_vc = user_joins_vc
|
||||
|
||||
ModuleABC.__init__(self)
|
||||
self._priorities[OnReadyABC] = 0
|
||||
self._logger.trace(__name__, f'Module {type(self)} loaded')
|
||||
|
||||
def _validate_init_time(self):
|
||||
try:
|
||||
start_time = self._config.get_configuration('Database_StartTime')
|
||||
init_time = round((datetime.now() - start_time).total_seconds(), 2)
|
||||
self._config.add_configuration('Database_InitTime', init_time)
|
||||
self._logger.debug(__name__, f'Database Init time: {init_time}s')
|
||||
# print warning if initialisation took too long
|
||||
if init_time >= 30:
|
||||
self._logger.warn(
|
||||
__name__, 'It takes long time to start the bot!')
|
||||
|
||||
# print error if initialisation took way too long
|
||||
elif init_time >= 90:
|
||||
self._logger.error(
|
||||
__name__, 'It takes very long time to start the bot!!!')
|
||||
except Exception as e:#
|
||||
self._logger.error(__name__, 'Database init time calculation failed', e)
|
||||
return
|
||||
|
||||
def _check_known_users(self):
|
||||
self._logger.debug(__name__, f'Start checking KnownUsers table, {len(self._bot.users)}')
|
||||
for u in self._bot.users:
|
||||
u: discord.User = u
|
||||
try:
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot')
|
||||
continue
|
||||
|
||||
user = self._known_users.find_user_by_discord_id(u.id)
|
||||
if user is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(__name__, f'Unknown user: {u.id}')
|
||||
self._logger.debug(__name__, f'Add user: {u.id}')
|
||||
self._known_users.add_user(KnownUser(u.id))
|
||||
self._db_context.save_changes()
|
||||
|
||||
user = self._known_users.find_user_by_discord_id(u.id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f'Cannot add user: {u.id}')
|
||||
|
||||
self._logger.debug(__name__, f'Added user: {u.id}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get user', e)
|
||||
|
||||
def _check_servers(self):
|
||||
self._logger.debug(__name__, f'Start checking Servers table')
|
||||
for g in self._bot.guilds:
|
||||
g: discord.Guild = g
|
||||
try:
|
||||
server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(__name__, f'Server not found in database: {g.id}')
|
||||
self._logger.debug(__name__, f'Add server: {g.id}')
|
||||
self._servers.add_server(Server(g.id))
|
||||
self._db_context.save_changes()
|
||||
|
||||
server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f'Cannot add server: {g.id}')
|
||||
|
||||
self._logger.debug(__name__, f'Added server: {g.id}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get server', e)
|
||||
|
||||
results = self._servers.get_servers()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f'Table Servers is empty!')
|
||||
|
||||
def _check_clients(self):
|
||||
self._logger.debug(__name__, f'Start checking Clients table')
|
||||
for g in self._bot.guilds:
|
||||
g: discord.Guild = g
|
||||
try:
|
||||
server: Server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f'Server not found in database: {g.id}')
|
||||
|
||||
client = self._clients.find_client_by_server_id(server.server_id)
|
||||
if client is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(__name__, f'Client for server {g.id} not found in database: {self._bot.user.id}')
|
||||
self._logger.debug(__name__, f'Add client: {self._bot.user.id}')
|
||||
self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server))
|
||||
self._db_context.save_changes()
|
||||
|
||||
client = self._clients.find_client_by_server_id(server.server_id)
|
||||
if client is None:
|
||||
self._logger.fatal(__name__, f'Cannot add client {self._bot.user.id} for server {g.id}')
|
||||
|
||||
self._logger.debug(__name__, f'Added client: {g.id}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get client', e)
|
||||
|
||||
results = self._servers.get_servers()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f'Table Servers is empty!')
|
||||
|
||||
def _check_users(self):
|
||||
self._logger.debug(__name__, f'Start checking Users table')
|
||||
for g in self._bot.guilds:
|
||||
g: discord.Guild = g
|
||||
|
||||
try:
|
||||
server = self._servers.find_server_by_discord_id(g.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f'Server not found in database: {g.id}')
|
||||
|
||||
for u in g.members:
|
||||
u: Union[discord.Member, discord.User] = u
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot')
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id)
|
||||
if user is not None:
|
||||
continue
|
||||
|
||||
self._logger.warn(__name__, f'User not found in database: {u.id}')
|
||||
self._logger.debug(__name__, f'Add user: {u.id}')
|
||||
self._users.add_user(User(u.id, 0, server))
|
||||
self._db_context.save_changes()
|
||||
|
||||
self._logger.debug(__name__, f'Added User: {u.id}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get User', e)
|
||||
|
||||
results = self._users.get_users()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f'Table Users is empty!')
|
||||
|
||||
def _check_user_joins(self):
|
||||
self._logger.debug(__name__, f'Start checking UserJoinedServers table')
|
||||
for guild in self._bot.guilds:
|
||||
guild: discord.Guild = guild
|
||||
|
||||
server = self._servers.find_server_by_discord_id(guild.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f'Server not found in database: {guild.id}')
|
||||
|
||||
try:
|
||||
for u in guild.members:
|
||||
u: discord.User = u
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot')
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f'User not found in database: {u.id}')
|
||||
|
||||
join = self._user_joins.find_active_user_joined_server_by_user_id(user.user_id)
|
||||
if join is not None:
|
||||
continue
|
||||
|
||||
m: discord.Member = u
|
||||
self._logger.warn(__name__, f'Active UserJoinedServer not found in database: {guild.id}:{u.id}@{m.joined_at}')
|
||||
self._logger.debug(__name__, f'Add UserJoinedServer: {guild.id}:{u.id}@{m.joined_at}')
|
||||
self._user_joins.add_user_joined_server(UserJoinedServer(user, m.joined_at, None))
|
||||
self._db_context.save_changes()
|
||||
|
||||
self._logger.debug(__name__, f'Added UserJoinedServer: {u.id}')
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get UserJoinedServer', e)
|
||||
|
||||
results = self._users.get_users()
|
||||
if results is None or len(results) == 0:
|
||||
self._logger.error(__name__, f'Table Users is empty!')
|
||||
|
||||
|
||||
joins = self._user_joins.get_user_joined_servers()
|
||||
for join in joins:
|
||||
join: UserJoinedServer = join
|
||||
if join.user.server.discord_server_id != guild.id:
|
||||
continue
|
||||
|
||||
if join.leaved_on is not None:
|
||||
continue
|
||||
|
||||
dc_user = guild.get_member(join.user.discord_id)
|
||||
if dc_user is None:
|
||||
self._logger.warn(__name__, f'User {join.user.discord_id} already left the server.')
|
||||
join.leaved_on = datetime.now()
|
||||
self._user_joins.update_user_joined_server(join)
|
||||
|
||||
self._db_context.save_changes()
|
||||
|
||||
def _check_user_joins_vc(self):
|
||||
self._logger.debug(__name__, f'Start checking UserJoinedVoiceChannel table')
|
||||
for guild in self._bot.guilds:
|
||||
guild: discord.Guild = guild
|
||||
|
||||
server = self._servers.find_server_by_discord_id(guild.id)
|
||||
if server is None:
|
||||
self._logger.fatal(__name__, f'Server not found in database: {guild.id}')
|
||||
|
||||
try:
|
||||
for u in guild.members:
|
||||
u: discord.User = u
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot')
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f'User not found in database: {u.id}')
|
||||
|
||||
join = self._user_joins_vc.find_active_user_joined_voice_channel_by_user_id(user.user_id)
|
||||
if join is None:
|
||||
continue
|
||||
|
||||
m: discord.Member = u
|
||||
self._logger.warn(__name__, f'Active UserJoinedVoiceChannel found in database: {guild.id}:{u.id}@{m.joined_at}')
|
||||
join.leaved_on = datetime.now()
|
||||
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{guild.id}')
|
||||
|
||||
if ((join.leaved_on - join.joined_on).total_seconds()/60/60) > server_st.max_voice_state_hours:
|
||||
join.leaved_on = join.joined_on + datetime.timedelta(hours=server_st.max_voice_state_hours)
|
||||
|
||||
self._user_joins_vc.update_user_joined_voice_channel(join)
|
||||
# todo: maybe add XP
|
||||
self._db_context.save_changes()
|
||||
|
||||
for u in guild.members:
|
||||
if u.bot:
|
||||
self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot')
|
||||
continue
|
||||
|
||||
m: discord.Member = u
|
||||
|
||||
if m.voice is None:
|
||||
continue
|
||||
|
||||
user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id)
|
||||
if user is None:
|
||||
self._logger.fatal(__name__, f'User not found in database: {u.id}')
|
||||
|
||||
join = UserJoinedVoiceChannel(user, m.voice.channel.id, datetime.now())
|
||||
self._user_joins_vc.add_user_joined_voice_channel(join)
|
||||
self._db_context.save_changes()
|
||||
self._logger.warn(__name__, f'VS {m.voice}')
|
||||
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f'Cannot get UserJoinedVoiceChannel', e)
|
||||
|
||||
async def on_ready(self):
|
||||
self._logger.debug(__name__, f'Module {type(self)} started')
|
||||
|
||||
self._check_known_users()
|
||||
self._check_servers()
|
||||
self._check_clients()
|
||||
self._check_users()
|
||||
self._check_user_joins()
|
||||
self._check_user_joins_vc()
|
||||
|
||||
self._validate_init_time()
|
||||
self._logger.trace(__name__, f'Module {type(self)} stopped')
|
17
src/modules/database/database_extension.py
Normal file
17
src/modules/database/database_extension.py
Normal file
@ -0,0 +1,17 @@
|
||||
from datetime import datetime
|
||||
|
||||
from cpl_core.application.application_extension_abc import ApplicationExtensionABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_core.logging import LoggerABC
|
||||
|
||||
|
||||
class DatabaseExtension(ApplicationExtensionABC):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
logger: LoggerABC = services.get_service(LoggerABC)
|
||||
logger.debug(__name__, 'Database extension started')
|
||||
config.add_configuration('Database_StartTime', datetime.now())
|
25
src/modules_core/__init__.py
Normal file
25
src/modules_core/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'modules_core'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
25
src/modules_core/abc/__init__.py
Normal file
25
src/modules_core/abc/__init__.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
gismo sh-edraft Gismo
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
sh-edraft Dicord bot Gismo
|
||||
|
||||
:copyright: (c) 2021 - 2022 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'modules_core.abc'
|
||||
__author__ = 'Sven Heidemann'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
|
||||
version_info = VersionInfo(major='0', minor='3', micro='0')
|
11
src/modules_core/abc/events/on_bulk_message_delete_abc.py
Normal file
11
src/modules_core/abc/events/on_bulk_message_delete_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnBulkMessageDeleteABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_bulk_message_delete(self, messages: list[discord.Message]): pass
|
10
src/modules_core/abc/events/on_connect_abc.py
Normal file
10
src/modules_core/abc/events/on_connect_abc.py
Normal file
@ -0,0 +1,10 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class OnConnectABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_connect(self): pass
|
10
src/modules_core/abc/events/on_disconnect_abc.py
Normal file
10
src/modules_core/abc/events/on_disconnect_abc.py
Normal file
@ -0,0 +1,10 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class OnDisconnectABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_disconnect(self): pass
|
10
src/modules_core/abc/events/on_error_abc.py
Normal file
10
src/modules_core/abc/events/on_error_abc.py
Normal file
@ -0,0 +1,10 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class OnErrorABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_error(self, event: str, *args, **kwargs): pass
|
12
src/modules_core/abc/events/on_group_join_abc.py
Normal file
12
src/modules_core/abc/events/on_group_join_abc.py
Normal file
@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGroupJoinABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_group_join(
|
||||
self, chhanel: discord.GroupChannel, user: discord.User): pass
|
11
src/modules_core/abc/events/on_group_remove_abc.py
Normal file
11
src/modules_core/abc/events/on_group_remove_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
class OnGroupRemoveABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_group_remove(
|
||||
self, chhanel: discord.GroupChannel, user: discord.User): pass
|
11
src/modules_core/abc/events/on_guild_available_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_available_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildAvailableABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_available(self, guild: discord.Guild): pass
|
12
src/modules_core/abc/events/on_guild_channel_create_abc.py
Normal file
12
src/modules_core/abc/events/on_guild_channel_create_abc.py
Normal file
@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildChannelCreateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_channel_create(self, channel: discord.abc.GuildChannel): pass
|
||||
|
12
src/modules_core/abc/events/on_guild_channel_delete_abc.py
Normal file
12
src/modules_core/abc/events/on_guild_channel_delete_abc.py
Normal file
@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildChannelDeleteABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_channel_delete(self, channel: discord.abc.GuildChannel): pass
|
||||
|
@ -0,0 +1,14 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildChannelPinsUpdateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_channel_pins_update(self, channel: discord.abc.GuildChannel, list_pin: Optional[datetime]): pass
|
||||
|
11
src/modules_core/abc/events/on_guild_channel_update_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_channel_update_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildChannelUpdateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_channel_update(self, before: discord.abc.GuildChannel, after: discord.abc.GuildChannel): pass
|
12
src/modules_core/abc/events/on_guild_emojis_update_abc.py
Normal file
12
src/modules_core/abc/events/on_guild_emojis_update_abc.py
Normal file
@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Sequence
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildEmojisUpdateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_emojis_update(self, guild: discord.Guild, before: Sequence[discord.Emoji], after: Sequence[discord.Emoji]): pass
|
@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildIntegrationsUpdateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_integrations_update(self, guild: discord.Guild): pass
|
||||
|
11
src/modules_core/abc/events/on_guild_join_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_join_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildJoinABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_join(self, guild: discord.Guild): pass
|
10
src/modules_core/abc/events/on_guild_remove_abc.py
Normal file
10
src/modules_core/abc/events/on_guild_remove_abc.py
Normal file
@ -0,0 +1,10 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildRemoveABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
@abstractmethod
|
||||
async def on_guild_remove(self, guild: discord.Guild): pass
|
11
src/modules_core/abc/events/on_guild_role_create_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_role_create_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildRoleCreateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_role_create(self, role: discord.Role): pass
|
11
src/modules_core/abc/events/on_guild_role_delete_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_role_delete_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildRoleDeleteABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_role_delete(self, role: discord.Role): pass
|
11
src/modules_core/abc/events/on_guild_role_update_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_role_update_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildRoleUpdateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_role_update(self, before: discord.Role, after: discord.Role): pass
|
11
src/modules_core/abc/events/on_guild_unavailable_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_unavailable_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildUnavailableABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_unavailable(self, guild: discord.Guild): pass
|
11
src/modules_core/abc/events/on_guild_update_abc.py
Normal file
11
src/modules_core/abc/events/on_guild_update_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnGuildUpdateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_guild_update(self, before: discord.Guild, after: discord.Guild): pass
|
12
src/modules_core/abc/events/on_invite_create_abc.py
Normal file
12
src/modules_core/abc/events/on_invite_create_abc.py
Normal file
@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnInviteCreateABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_invite_create(self, invite: discord.Invite): pass
|
||||
|
11
src/modules_core/abc/events/on_invite_delete_abc.py
Normal file
11
src/modules_core/abc/events/on_invite_delete_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnInviteDeleteABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_invite_delete(self, invite: discord.Invite): pass
|
11
src/modules_core/abc/events/on_member_ban_abc.py
Normal file
11
src/modules_core/abc/events/on_member_ban_abc.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnMemberBanABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
async def on_member_ban(self, guild: discord.Guild, user: discord.User): pass
|
12
src/modules_core/abc/events/on_member_join_abc.py
Normal file
12
src/modules_core/abc/events/on_member_join_abc.py
Normal file
@ -0,0 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import discord
|
||||
|
||||
|
||||
class OnMemberJoinABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
|
||||
@abstractmethod
|
||||
async def on_member_join(self, member: discord.Member): pass
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user