Merge pull request 'A-0.2 - Datenbankverbindung' (#35) from 0.2 into Alpha

Reviewed-on: #35
This commit is contained in:
Sven Heidemann 2021-12-01 17:57:51 +01:00
commit be692326d6
43 changed files with 682 additions and 265 deletions

1
.gitignore vendored
View File

@ -140,4 +140,5 @@ cython_debug/
# custom vs code # custom vs code
PythonImportHelper-v2-Completion.json PythonImportHelper-v2-Completion.json
appsettings.*.json

View File

@ -6,11 +6,11 @@
"gismo-cli": "src/gismo_cli/gismo-cli.json", "gismo-cli": "src/gismo_cli/gismo-cli.json",
"gismo-core": "src/gismo_core/gismo-core.json", "gismo-core": "src/gismo_core/gismo-core.json",
"gismo-data": "src/gismo_data/gismo-data.json", "gismo-data": "src/gismo_data/gismo-data.json",
"cpl-extension": "src/cpl_extension/cpl-extension.json",
"modules-core": "src/modules_core/modules-core.json", "modules-core": "src/modules_core/modules-core.json",
"boot-log": "src/modules/boot_log/boot-log.json", "boot-log": "src/modules/boot_log/boot-log.json",
"level-generator": "tools/level_generator/level-generator.json", "level-generator": "tools/level_generator/level-generator.json",
"ontime-calculator": "tools/ontime_calculator/ontime-calculator.json" "ontime-calculator": "tools/ontime_calculator/ontime-calculator.json",
"database": "src/modules/database/database.json"
}, },
"Scripts": { "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", "build-start": "cd src/gismo_cli; echo 'gismo-cli:'; cpl build; cd ../gismo; echo 'gismo:'; cpl build; cd ../../dist/gismo/build/gismo; bash gismo",

View File

@ -1,25 +0,0 @@
# -*- 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__ = 'cpl_extension'
__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')

View File

@ -1,44 +0,0 @@
{
"ProjectSettings": {
"Name": "cpl-extension",
"Version": {
"Major": "0",
"Minor": "1",
"Micro": "0"
},
"Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de",
"Description": "sh-edraft Gismo - cpl extension - database core",
"LongDescription": "sh-edraft Dicord bot Gismo - database implementation of cpl.database",
"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.10.2",
"sh_cpl-query>=2021.10.3"
],
"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": []
}
}

View File

@ -15,11 +15,11 @@ __title__ = 'gismo'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -1,5 +0,0 @@
{
"Discord": {
"Token": "OTExNjM5NjE2MTAzMjUyMDM4.YZkUjQ.MCqPkOTIMdvMYrmt47lfrZ0inhg"
}
}

View File

@ -1,28 +0,0 @@
{
"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_dev.log",
"ConsoleLogLevel": "DEBUG",
"FileLogLevel": "DEBUG"
},
"Discord": {
"Token": "OTA5ODc4NDcyNzExNzU3ODQ1.YZKsXA.BXBszIF3z3wHpoe9s3pKfO3Yd5c"
},
"Bot": {
"Prefix": "!gd",
"Servers": [
{
"Id": "910199451145076828",
"LoginMessageChannelId": "910199452915093588",
"LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert",
"MessageDeleteTimer": 2
}
]
}
}

View File

@ -1,22 +0,0 @@
{
"LoggingSettings": {
"Path": "logs/",
"Filename": "log_dev.log",
"ConsoleLogLevel": "TRACE",
"FileLogLevel": "TRACE"
},
"Discord": {
"Token": "OTExNTc0NDQyMzMxNzM0MDI2.YZjX2w.9yhsrTfrmkoDUqRJVzV5FVEwF3U"
},
"Bot": {
"Prefix": "!gde",
"Servers": [
{
"Id": "910199451145076828",
"LoginMessageChannelId": "910199452915093588",
"LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert",
"MessageDeleteTimer": 2
}
]
}
}

View File

@ -1,22 +0,0 @@
{
"LoggingSettings": {
"Path": "logs/",
"Filename": "log_dev.log",
"ConsoleLogLevel": "TRACE",
"FileLogLevel": "TRACE"
},
"Discord": {
"Token": "OTExNTc0NDQyMzMxNzM0MDI2.YZjX2w.9yhsrTfrmkoDUqRJVzV5FVEwF3U"
},
"Bot": {
"Prefix": "!gde",
"Servers": [
{
"Id": "910199451145076828",
"LoginMessageChannelId": "910199452915093588",
"LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert",
"MessageDeleteTimer": 2
}
]
}
}

View File

@ -1,28 +0,0 @@
{
"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": "OTA5ODc3NDg3MjEzODk5ODQ3.YZKrcQ.qwfDWBFdkOzxZZT10jUWG5fY2RA"
},
"Bot": {
"Prefix": "!g",
"Servers": [
{
"Id": "511824600884051979",
"LoginMessageChannelId": "521260270757347328",
"LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert",
"MessageDeleteTimer": 2
}
]
}
}

View File

@ -1,28 +0,0 @@
{
"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_staging_$start_time.log",
"ConsoleLogLevel": "DEBUG",
"FileLogLevel": "DEBUG"
},
"Discord": {
"Token": "OTEwMjAxNjA1NDkwNjEwMjA3.YZPZTQ.kvMUuDUH_-qsllgkch8LYmXcKlo"
},
"Bot": {
"Prefix": "!gt",
"Servers": [
{
"Id": "511824600884051979",
"LoginMessageChannelId": "521260270757347328",
"LoginMessage": "Ich bin on the line :D\nDer Start hat {} Sekunden gedauert",
"MessageDeleteTimer": 2
}
]
}
}

View File

@ -3,7 +3,7 @@
"Name": "gismo", "Name": "gismo",
"Version": { "Version": {
"Major": "0", "Major": "0",
"Minor": "1", "Minor": "2",
"Micro": "0" "Micro": "0"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
@ -16,8 +16,8 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl-core>=2021.10.2", "sh_cpl-core>=2021.11.0",
"sh_cpl-query>=2021.10.3", "sh_cpl-query>=2021.11.0",
"discord.py==1.7.3" "discord.py==1.7.3"
], ],
"PythonVersion": ">=3.9.2", "PythonVersion": ">=3.9.2",
@ -47,7 +47,6 @@
"ProjectReferences": [ "ProjectReferences": [
"../gismo_core/gismo-core.json", "../gismo_core/gismo-core.json",
"../gismo_data/gismo-data.json", "../gismo_data/gismo-data.json",
"../cpl_extension/cpl-extension.json",
"../modules_core/modules-core.json", "../modules_core/modules-core.json",
"../modules/boot_log/boot-log.json" "../modules/boot_log/boot-log.json"
] ]

View File

@ -6,6 +6,7 @@ from cpl_core.application import ApplicationBuilder
from gismo.application import Gismo from gismo.application import Gismo
from gismo.startup import Startup from gismo.startup import Startup
from modules.boot_log.boot_log_extension import BootLogExtension from modules.boot_log.boot_log_extension import BootLogExtension
from modules.database.database_extension import DatabaseExtension
class Main: class Main:
@ -15,6 +16,7 @@ class Main:
async def main(self): async def main(self):
app_builder = ApplicationBuilder(Gismo) app_builder = ApplicationBuilder(Gismo)
app_builder.use_extension(DatabaseExtension)
app_builder.use_extension(BootLogExtension) app_builder.use_extension(BootLogExtension)
app_builder.use_startup(Startup) app_builder.use_startup(Startup)
self._gismo: Gismo = await app_builder.build_async() self._gismo: Gismo = await app_builder.build_async()
@ -32,7 +34,6 @@ if __name__ == '__main__':
except KeyboardInterrupt: except KeyboardInterrupt:
ml.run_until_complete(main.stop()) ml.run_until_complete(main.stop())
# (( # ((
# ( `) # ( `)
# ; / , # ; / ,

View File

@ -1,9 +1,10 @@
from datetime import datetime
import os import os
from datetime import datetime
from typing import Optional from typing import Optional
from cpl_core.application import StartupABC from cpl_core.application import StartupABC
from cpl_core.configuration import ConfigurationABC from cpl_core.configuration import ConfigurationABC
from cpl_core.database import DatabaseSettings
from cpl_core.dependency_injection import (ServiceCollectionABC, from cpl_core.dependency_injection import (ServiceCollectionABC,
ServiceProviderABC) ServiceProviderABC)
from cpl_core.environment import ApplicationEnvironment from cpl_core.environment import ApplicationEnvironment
@ -12,7 +13,13 @@ from gismo_core.abc.bot_service_abc import BotServiceABC
from gismo_core.abc.message_service_abc import MessageServiceABC from gismo_core.abc.message_service_abc import MessageServiceABC
from gismo_core.service.bot_service import BotService from gismo_core.service.bot_service import BotService
from gismo_core.service.message_service import MessageService from gismo_core.service.message_service import MessageService
from gismo_data.abc.server_repository_abc import ServerRepositoryABC
from gismo_data.abc.user_repository_abc import UserRepositoryABC
from gismo_data.db_context import DBContext
from gismo_data.service.server_repository_service import ServerRepositoryService
from gismo_data.service.user_repository_service import UserRepositoryService
from modules.boot_log.boot_log import BootLog 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_abc import ModuleABC
from modules_core.abc.module_service_abc import ModuleServiceABC from modules_core.abc.module_service_abc import ModuleServiceABC
from modules_core.service.module_service import ModuleService from modules_core.service.module_service import ModuleService
@ -42,10 +49,16 @@ class Startup(StartupABC):
async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC: async def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
services.add_logging() services.add_logging()
services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings))
services.add_singleton(ModuleServiceABC, ModuleService) services.add_singleton(ModuleServiceABC, ModuleService)
services.add_singleton(BotServiceABC, BotService) services.add_singleton(BotServiceABC, BotService)
services.add_transient(MessageServiceABC, MessageService) services.add_transient(MessageServiceABC, MessageService)
services.add_transient(ServerRepositoryABC, ServerRepositoryService)
services.add_transient(UserRepositoryABC, UserRepositoryService)
services.add_transient(ModuleABC, Database)
services.add_transient(ModuleABC, BootLog) services.add_transient(ModuleABC, BootLog)
provider: ServiceProviderABC = services.build_service_provider() provider: ServiceProviderABC = services.build_service_provider()

View File

@ -16,8 +16,8 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl-core>=2021.10.2", "sh_cpl-core>=2021.11.0",
"sh_cpl-query>=2021.10.3" "sh_cpl-query>=2021.11.0"
], ],
"PythonVersion": ">=3.9.2", "PythonVersion": ">=3.9.2",
"PythonPath": { "PythonPath": {

View File

@ -15,11 +15,11 @@ __title__ = 'gismo_core'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports # imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -15,11 +15,11 @@ __title__ = 'gismo_core.abc'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports # imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -15,11 +15,11 @@ __title__ = 'gismo_core.configuration'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports # imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -16,8 +16,8 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl-core>=2021.10.2", "sh_cpl-core>=2021.11.0",
"sh_cpl-query>=2021.10.3" "sh_cpl-query>=2021.11.0"
], ],
"PythonVersion": ">=3.9.2", "PythonVersion": ">=3.9.2",
"PythonPath": { "PythonPath": {

View File

@ -15,11 +15,11 @@ __title__ = 'gismo_core.service'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports # imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -36,7 +36,7 @@ class BotService(BotServiceABC, commands.Bot):
self._bot_settings: BotSettings = bot_settings self._bot_settings: BotSettings = bot_settings
# setup super # setup super
commands.Bot.__init__(self, command_prefix=bot_settings.prefix, help_command=None) commands.Bot.__init__(self, command_prefix=bot_settings.prefix, help_command=None, intents=discord.Intents().all())
async def start_async(self): async def start_async(self):
self._logger.trace(__name__, 'Try to connect to discord') self._logger.trace(__name__, 'Try to connect to discord')

View File

@ -1,25 +1 @@
# -*- coding: utf-8 -*- # imports
"""
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.1.0'
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0')

View File

@ -0,0 +1 @@
# imports

View 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

View File

@ -0,0 +1,33 @@
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_user_by_discord_id(self, discord_id: int) -> User: pass
@abstractmethod
def find_user_by_discord_id(self, discord_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

View File

@ -0,0 +1,38 @@
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)
for table in self._tables:
self._logger.debug(__name__, f"Create table if not exists: {table}")
self._logger.trace(__name__, f'Send SQL command: {table.get_create_string()}')
self._db.cursor.execute(table.get_create_string())
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)

View File

@ -16,8 +16,8 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl-core>=2021.10.2", "sh_cpl-core>=2021.11.0",
"sh_cpl-query>=2021.10.3" "sh_cpl-query>=2021.11.0"
], ],
"PythonVersion": ">=3.9.2", "PythonVersion": ">=3.9.2",
"PythonPath": { "PythonPath": {

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,83 @@
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_create_string() -> str:
return 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`)
);
""")
@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._id};
""")
@property
def delete_string(self) -> str:
return str(f"""
DELETE FROM `Servers`
WHERE `Id` = {self._id};
""")

View File

@ -0,0 +1,104 @@
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_create_string() -> str:
return 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`)
);
""")
@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};
""")
@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 `Id` = {self._id};
""")
@property
def delete_string(self) -> str:
return str(f"""
DELETE FROM `Users`
WHERE `Id` = {self._id};
""")

View File

@ -0,0 +1 @@
# imports

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

View File

@ -0,0 +1,83 @@
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))
return User(
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) -> User:
self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_string(discord_id)}')
result = self._context.select(User.get_select_by_discord_id_string(discord_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(self, discord_id: int) -> Optional[User]:
self._logger.trace(__name__, f'Send SQL command: {User.get_select_by_discord_id_string(discord_id)}')
result = self._context.select(User.get_select_by_discord_id_string(discord_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)

View File

@ -15,11 +15,11 @@ __title__ = 'modules.boot_log'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -16,8 +16,8 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl-core>=2021.10.2", "sh_cpl-core>=2021.11.0",
"sh_cpl-query>=2021.10.3" "sh_cpl-query>=2021.11.0"
], ],
"PythonVersion": ">=3.9.2", "PythonVersion": ">=3.9.2",
"PythonPath": { "PythonPath": {

View File

@ -0,0 +1 @@
# imports:

View 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": []
}
}

View File

@ -0,0 +1,120 @@
import asyncio
from datetime import datetime
import time
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.abc.message_service_abc import MessageServiceABC
from gismo_core.configuration.server_settings import ServerSettings
from gismo_data.abc.user_repository_abc import UserRepositoryABC
from gismo_data.model.server import Server
from gismo_data.model.user import User
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
):
self._config = config
self._logger = logger
self._bot = bot
self._db_context = db_context
self._servers = server_repo
self._users = user_repo
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_servers(self):
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:
return
self._logger.warn(__name__, f'Server not found in database: {g.id}')
self._logger.debug(__name__, f'Add server: {g.id}')
self._servers.add_server(Server(g.id))
self._db_context.save_changes()
self._logger.debug(__name__, f'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_users(self):
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}')
break
for u in g.members:
u: discord.Member = u
user = self._users.find_user_by_discord_id(u.id)
if user is not None:
break
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!')
async def on_ready(self):
self._logger.debug(__name__, f'Module {type(self)} started')
self._check_servers()
self._check_users()
self._validate_init_time()
self._logger.trace(__name__, f'Module {type(self)} stopped')

View 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())

View File

@ -15,11 +15,11 @@ __title__ = 'modules_core'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports # imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -15,11 +15,11 @@ __title__ = 'modules_core.abc'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports # imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')

View File

@ -16,8 +16,8 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl-core>=2021.10.2", "sh_cpl-core>=2021.11.0",
"sh_cpl-query>=2021.10.3" "sh_cpl-query>=2021.11.0"
], ],
"PythonVersion": ">=3.9.2", "PythonVersion": ">=3.9.2",
"PythonPath": { "PythonPath": {

View File

@ -15,11 +15,11 @@ __title__ = 'modules_core.service'
__author__ = 'Sven Heidemann' __author__ = 'Sven Heidemann'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de'
__version__ = '0.1.0' __version__ = '0.2.0'
from collections import namedtuple from collections import namedtuple
# imports # imports
VersionInfo = namedtuple('VersionInfo', 'major minor micro') VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='1', micro='0') version_info = VersionInfo(major='0', minor='2', micro='0')