From 62d56a22471712776759d171e2405e29210f880a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 1 Dec 2021 19:34:39 +0100 Subject: [PATCH 01/48] Created base module --- cpl-workspace.json | 3 ++- src/gismo/startup.py | 2 ++ src/modules/base/__init__.py | 1 + src/modules/base/base.json | 43 ++++++++++++++++++++++++++++++++++++ src/modules/base/base.py | 29 ++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/modules/base/__init__.py create mode 100644 src/modules/base/base.json create mode 100644 src/modules/base/base.py diff --git a/cpl-workspace.json b/cpl-workspace.json index b0db2c0..891044f 100644 --- a/cpl-workspace.json +++ b/cpl-workspace.json @@ -10,7 +10,8 @@ "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" + "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", diff --git a/src/gismo/startup.py b/src/gismo/startup.py index f359a18..3d2d05f 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -18,6 +18,7 @@ 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.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 @@ -59,6 +60,7 @@ class Startup(StartupABC): services.add_transient(UserRepositoryABC, UserRepositoryService) services.add_transient(ModuleABC, Database) + services.add_transient(ModuleABC, Base) services.add_transient(ModuleABC, BootLog) provider: ServiceProviderABC = services.build_service_provider() diff --git a/src/modules/base/__init__.py b/src/modules/base/__init__.py new file mode 100644 index 0000000..ad5eca3 --- /dev/null +++ b/src/modules/base/__init__.py @@ -0,0 +1 @@ +# imports: diff --git a/src/modules/base/base.json b/src/modules/base/base.json new file mode 100644 index 0000000..7c5150a --- /dev/null +++ b/src/modules/base/base.json @@ -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": [] + } +} \ No newline at end of file diff --git a/src/modules/base/base.py b/src/modules/base/base.py new file mode 100644 index 0000000..530b3cd --- /dev/null +++ b/src/modules/base/base.py @@ -0,0 +1,29 @@ +import discord +from cpl_core.logging.logger_abc import LoggerABC + +from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC +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, OnMessageABC, OnVoiceStateUpdateABC): + + def __init__(self, logger: LoggerABC): + + self._logger = logger + + ModuleABC.__init__(self) + self._priorities[OnMemberJoinABC] = 1 + self._priorities[OnMessageABC] = 30 + self._priorities[OnVoiceStateUpdateABC] = 10 + self._logger.trace(__name__, f'Module {type(self)} loaded') + + async def on_member_join(self, member: discord.Member): + self._logger.debug(__name__, f'Module {type(self)} started') + + async def on_message(self, message: discord.Message): + self._logger.debug(__name__, f'Module {type(self)} started') + + 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') -- 2.45.2 From 60172e0cfe4705fe3f73fd245315c9fc695d85ac Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 1 Dec 2021 20:03:06 +0100 Subject: [PATCH 02/48] Added client model --- src/gismo_data/model/client.py | 115 +++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/gismo_data/model/client.py diff --git a/src/gismo_data/model/client.py b/src/gismo_data/model/client.py new file mode 100644 index 0000000..ca56e9f --- /dev/null +++ b/src/gismo_data/model/client.py @@ -0,0 +1,115 @@ +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 + + @staticmethod + def get_create_string() -> str: + return 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(`UserId`) + ); + """) + + @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}; + """) + + @property + def insert_string(self) -> str: + return str(f""" + INSERT INTO `Clients` ( + `SentMessageCount`, + `ReceivedMessageCount`, + `DeletedMessageCount`, + `ReceivedCommandsCount`, + `MovedUsersCount`, + `ServerId`, + `CreatedAt`, + `LastModifiedAt` + ) VALUES ( + {self._sent_message_count}, + {self._received_message_count}, + {self._deleted_message_count}, + {self._received_message_count}, + {self._moved_users_count}, + {self._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 `Id` = {self._client_id}; + """) + + @property + def delete_string(self) -> str: + return str(f""" + DELETE FROM `Clients` + WHERE `Id` = {self._client_id}; + """) -- 2.45.2 From ce70e816fefb54b5d22f2ad99bd5e47c986ebd46 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 1 Dec 2021 20:03:14 +0100 Subject: [PATCH 03/48] Improved other models --- src/gismo_data/model/server.py | 4 ++-- src/gismo_data/model/user.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gismo_data/model/server.py b/src/gismo_data/model/server.py index 207bc35..5f9e9e5 100644 --- a/src/gismo_data/model/server.py +++ b/src/gismo_data/model/server.py @@ -72,12 +72,12 @@ class Server(TableABC): UPDATE `Servers` SET `DiscordServerId` = {self._discord_server_id}, `LastModifiedAt` = '{self._modified_at}' - WHERE `Id` = {self._id}; + WHERE `Id` = {self._server_id}; """) @property def delete_string(self) -> str: return str(f""" DELETE FROM `Servers` - WHERE `Id` = {self._id}; + WHERE `Id` = {self._server_id}; """) diff --git a/src/gismo_data/model/user.py b/src/gismo_data/model/user.py index 3bbc27a..2fae830 100644 --- a/src/gismo_data/model/user.py +++ b/src/gismo_data/model/user.py @@ -93,12 +93,12 @@ class User(TableABC): UPDATE `Users` SET `XP` = {self._xp}, `LastModifiedAt` = '{self._modified_at}' - WHERE `Id` = {self._id}; + WHERE `Id` = {self._user_id}; """) @property def delete_string(self) -> str: return str(f""" DELETE FROM `Users` - WHERE `Id` = {self._id}; + WHERE `Id` = {self._user_id}; """) -- 2.45.2 From e15ae555be4a9ef6927ecba8f28ad24b54bdc191 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 1 Dec 2021 20:19:34 +0100 Subject: [PATCH 04/48] Added client repos --- src/gismo/startup.py | 9 +- src/gismo_data/abc/client_repository_abc.py | 32 ++++++ .../service/client_repository_service.py | 97 +++++++++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 src/gismo_data/abc/client_repository_abc.py create mode 100644 src/gismo_data/service/client_repository_service.py diff --git a/src/gismo/startup.py b/src/gismo/startup.py index 3d2d05f..4ddd38d 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -9,6 +9,7 @@ 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 @@ -16,7 +17,10 @@ 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.client_repository_service import ( + ClientRepositoryABC, ClientRepositoryService) +from gismo_data.service.server_repository_service import \ + ServerRepositoryService from gismo_data.service.user_repository_service import UserRepositoryService from modules.base.base import Base from modules.boot_log.boot_log import BootLog @@ -58,7 +62,8 @@ class Startup(StartupABC): services.add_transient(ServerRepositoryABC, ServerRepositoryService) services.add_transient(UserRepositoryABC, UserRepositoryService) - + services.add_transient(ClientRepositoryABC, ClientRepositoryService) + services.add_transient(ModuleABC, Database) services.add_transient(ModuleABC, Base) services.add_transient(ModuleABC, BootLog) diff --git a/src/gismo_data/abc/client_repository_abc.py b/src/gismo_data/abc/client_repository_abc.py new file mode 100644 index 0000000..b55b63e --- /dev/null +++ b/src/gismo_data/abc/client_repository_abc.py @@ -0,0 +1,32 @@ +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 add_client(self, client: Client): pass + + @abstractmethod + def update_client(self, client: Client): pass + + @abstractmethod + def delete_client(self, client: Client): pass diff --git a/src/gismo_data/service/client_repository_service.py b/src/gismo_data/service/client_repository_service.py new file mode 100644 index 0000000..bd0f410 --- /dev/null +++ b/src/gismo_data/service/client_repository_service.py @@ -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.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 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) -- 2.45.2 From d27964372dae9a1c98ca54a3b6f79bda7bb56b34 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 1 Dec 2021 20:30:27 +0100 Subject: [PATCH 05/48] Added getter --- src/gismo_data/model/client.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/gismo_data/model/client.py b/src/gismo_data/model/client.py index ca56e9f..4023f82 100644 --- a/src/gismo_data/model/client.py +++ b/src/gismo_data/model/client.py @@ -31,6 +31,38 @@ class Client(TableABC): 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_id + + @property + def sent_message_count(self) -> int: + return self._sent_message_count + + @property + def received_message_count(self) -> int: + return self._received_message_count + + @property + def deleted_message_count(self) -> int: + return self._deleted_message_count + + @property + def received_command_count(self) -> int: + return self._received_command_count + + @property + def moved_users_count(self) -> int: + return self._moved_users_count + + @property + def server(self) -> Server: + return self._server + @staticmethod def get_create_string() -> str: return str(f""" -- 2.45.2 From 026dfe0dfbc7ee6873e9f95b033c61e1bcbbed51 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 1 Dec 2021 20:49:58 +0100 Subject: [PATCH 06/48] Added logic to load clients on_ready --- src/gismo_data/abc/client_repository_abc.py | 3 ++ src/gismo_data/model/client.py | 15 ++++-- .../service/client_repository_service.py | 19 +++++++ src/modules/database/database.py | 54 ++++++++++++++++--- 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/gismo_data/abc/client_repository_abc.py b/src/gismo_data/abc/client_repository_abc.py index b55b63e..6b1dcdb 100644 --- a/src/gismo_data/abc/client_repository_abc.py +++ b/src/gismo_data/abc/client_repository_abc.py @@ -22,6 +22,9 @@ class ClientRepositoryABC(ABC): @abstractmethod def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: pass + @abstractmethod + def find_client_by_server_id(self, discord_id: int) -> Optional[Client]: pass + @abstractmethod def add_client(self, client: Client): pass diff --git a/src/gismo_data/model/client.py b/src/gismo_data/model/client.py index 4023f82..9048ea4 100644 --- a/src/gismo_data/model/client.py +++ b/src/gismo_data/model/client.py @@ -37,7 +37,7 @@ class Client(TableABC): @property def discord_id(self) -> int: - return self._discord_id + return self._discord_client_id @property def sent_message_count(self) -> int: @@ -78,7 +78,7 @@ class Client(TableABC): `CreatedAt` DATETIME(6), `LastModifiedAt` DATETIME(6), FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`), - PRIMARY KEY(`UserId`) + PRIMARY KEY(`ClientId`) ); """) @@ -102,10 +102,18 @@ class Client(TableABC): WHERE `DiscordClientId` = {id}; """) + @staticmethod + def get_select_by_server_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `Clients` + WHERE `ServerId` = {id}; + """) + @property def insert_string(self) -> str: return str(f""" INSERT INTO `Clients` ( + `DiscordClientId`, `SentMessageCount`, `ReceivedMessageCount`, `DeletedMessageCount`, @@ -115,12 +123,13 @@ class Client(TableABC): `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.id}, + {self._server.server_id}, '{self._created_at}', '{self._modified_at}' ); diff --git a/src/gismo_data/service/client_repository_service.py b/src/gismo_data/service/client_repository_service.py index bd0f410..8f0f5a1 100644 --- a/src/gismo_data/service/client_repository_service.py +++ b/src/gismo_data/service/client_repository_service.py @@ -83,6 +83,25 @@ class ClientRepositoryService(ClientRepositoryABC): 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 add_client(self, client: Client): self._logger.trace(__name__, f'Send SQL command: {client.insert_string}') diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 7dd1569..34fc3a7 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -1,16 +1,19 @@ import asyncio -from datetime import datetime import time +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 import LoggerABC - +from discord.ext import commands 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.user_repository_abc import UserRepositoryABC +from gismo_data.model.client import Client from gismo_data.model.server import Server from gismo_data.model.user import User from gismo_data.service.user_repository_service import ServerRepositoryABC @@ -27,7 +30,8 @@ class Database(ModuleABC, OnReadyABC): bot: BotServiceABC, db_context: DatabaseContextABC, server_repo: ServerRepositoryABC, - user_repo: UserRepositoryABC + user_repo: UserRepositoryABC, + client_repo: ClientRepositoryABC, ): self._config = config @@ -36,6 +40,7 @@ class Database(ModuleABC, OnReadyABC): self._db_context = db_context self._servers = server_repo self._users = user_repo + self._clients = client_repo ModuleABC.__init__(self) self._priorities[OnReadyABC] = 0 @@ -66,12 +71,16 @@ class Database(ModuleABC, OnReadyABC): try: server = self._servers.find_server_by_discord_id(g.id) if server is not None: - return + break 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: @@ -80,6 +89,35 @@ class Database(ModuleABC, OnReadyABC): 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): + 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: + break + + 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): for g in self._bot.guilds: @@ -89,10 +127,13 @@ class Database(ModuleABC, OnReadyABC): 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 + if u.bot: + self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot') + break + user = self._users.find_user_by_discord_id(u.id) if user is not None: break @@ -114,7 +155,8 @@ class Database(ModuleABC, OnReadyABC): self._logger.debug(__name__, f'Module {type(self)} started') self._check_servers() + self._check_clients() self._check_users() self._validate_init_time() - self._logger.trace(__name__, f'Module {type(self)} stopped') \ No newline at end of file + self._logger.trace(__name__, f'Module {type(self)} stopped') -- 2.45.2 From b8e340f66108a023deaf83d94fdf23da7390aef6 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 2 Dec 2021 17:35:03 +0100 Subject: [PATCH 07/48] Added known user model --- src/gismo_data/model/known_user.py | 80 ++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/gismo_data/model/known_user.py diff --git a/src/gismo_data/model/known_user.py b/src/gismo_data/model/known_user.py new file mode 100644 index 0000000..8f0f38e --- /dev/null +++ b/src/gismo_data/model/known_user.py @@ -0,0 +1,80 @@ +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_create_string() -> str: + return str(f""" + CREATE TABLE IF NOT EXISTS `KnownUsers` ( + `KnownUserId` BIGINT NOT NULL AUTO_INCREMENT, + `DiscordId` BIGINT NOT NULL, + `ServerId` BIGINT, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + PRIMARY KEY(`KnownUserId`) + ); + """) + + @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}; + """) -- 2.45.2 From 2c29b45f5a9d7e20c32f33e01f6f7721bb05ddeb Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 2 Dec 2021 17:40:23 +0100 Subject: [PATCH 08/48] Added known user repos --- .../abc/known_user_repository_abc.py | 30 +++++++ .../service/known_user_repository_service.py | 79 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/gismo_data/abc/known_user_repository_abc.py create mode 100644 src/gismo_data/service/known_user_repository_service.py diff --git a/src/gismo_data/abc/known_user_repository_abc.py b/src/gismo_data/abc/known_user_repository_abc.py new file mode 100644 index 0000000..5370677 --- /dev/null +++ b/src/gismo_data/abc/known_user_repository_abc.py @@ -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 diff --git a/src/gismo_data/service/known_user_repository_service.py b/src/gismo_data/service/known_user_repository_service.py new file mode 100644 index 0000000..f9a30e5 --- /dev/null +++ b/src/gismo_data/service/known_user_repository_service.py @@ -0,0 +1,79 @@ +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.known_user import KnownUser + + +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[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], + result[4], + self._servers.get_server_by_id(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) -- 2.45.2 From 0fd99cc6bae089a6fd9d63c21c7c700a5d94cd1c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 2 Dec 2021 17:41:44 +0100 Subject: [PATCH 09/48] Added repos to startup --- src/gismo/startup.py | 3 +++ src/gismo_data/service/known_user_repository_service.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gismo/startup.py b/src/gismo/startup.py index 4ddd38d..307aa35 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -14,11 +14,13 @@ 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.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.client_repository_service import ( ClientRepositoryABC, ClientRepositoryService) +from gismo_data.service.known_user_repository_service import KnownUserRepositoryService from gismo_data.service.server_repository_service import \ ServerRepositoryService from gismo_data.service.user_repository_service import UserRepositoryService @@ -63,6 +65,7 @@ class Startup(StartupABC): services.add_transient(ServerRepositoryABC, ServerRepositoryService) services.add_transient(UserRepositoryABC, UserRepositoryService) services.add_transient(ClientRepositoryABC, ClientRepositoryService) + services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService) services.add_transient(ModuleABC, Database) services.add_transient(ModuleABC, Base) diff --git a/src/gismo_data/service/known_user_repository_service.py b/src/gismo_data/service/known_user_repository_service.py index f9a30e5..738597f 100644 --- a/src/gismo_data/service/known_user_repository_service.py +++ b/src/gismo_data/service/known_user_repository_service.py @@ -8,7 +8,7 @@ from gismo_data.abc.user_repository_abc import UserRepositoryABC from gismo_data.model.known_user import KnownUser -class UserRepositoryService(UserRepositoryABC): +class KnownUserRepositoryService(UserRepositoryABC): def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC): self._logger = logger -- 2.45.2 From c949efea508053456be92045dd99ad5300d6b9d4 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 2 Dec 2021 17:51:11 +0100 Subject: [PATCH 10/48] Improved database module --- src/gismo_data/model/known_user.py | 1 - .../service/known_user_repository_service.py | 6 +-- src/modules/database/database.py | 44 ++++++++++++++++--- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/gismo_data/model/known_user.py b/src/gismo_data/model/known_user.py index 8f0f38e..73ff562 100644 --- a/src/gismo_data/model/known_user.py +++ b/src/gismo_data/model/known_user.py @@ -29,7 +29,6 @@ class KnownUser(TableABC): CREATE TABLE IF NOT EXISTS `KnownUsers` ( `KnownUserId` BIGINT NOT NULL AUTO_INCREMENT, `DiscordId` BIGINT NOT NULL, - `ServerId` BIGINT, `CreatedAt` DATETIME(6), `LastModifiedAt` DATETIME(6), PRIMARY KEY(`KnownUserId`) diff --git a/src/gismo_data/service/known_user_repository_service.py b/src/gismo_data/service/known_user_repository_service.py index 738597f..d349ea5 100644 --- a/src/gismo_data/service/known_user_repository_service.py +++ b/src/gismo_data/service/known_user_repository_service.py @@ -2,13 +2,13 @@ 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.abc.user_repository_abc import UserRepositoryABC from gismo_data.model.known_user import KnownUser -class KnownUserRepositoryService(UserRepositoryABC): +class KnownUserRepositoryService(KnownUserRepositoryABC): def __init__(self, logger: LoggerABC, db_context: DatabaseContextABC, servers: ServerRepositoryABC): self._logger = logger @@ -16,7 +16,7 @@ class KnownUserRepositoryService(UserRepositoryABC): self._servers = servers - UserRepositoryABC.__init__(self) + KnownUserRepositoryABC.__init__(self) def get_users(self) -> List[KnownUser]: users = List(KnownUser) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 34fc3a7..7504f45 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -1,19 +1,15 @@ -import asyncio -import time 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 import LoggerABC -from discord.ext import commands 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.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.service.user_repository_service import ServerRepositoryABC @@ -32,6 +28,7 @@ class Database(ModuleABC, OnReadyABC): server_repo: ServerRepositoryABC, user_repo: UserRepositoryABC, client_repo: ClientRepositoryABC, + known_users: KnownUserRepositoryABC ): self._config = config @@ -41,6 +38,7 @@ class Database(ModuleABC, OnReadyABC): self._servers = server_repo self._users = user_repo self._clients = client_repo + self._known_users = known_users ModuleABC.__init__(self) self._priorities[OnReadyABC] = 0 @@ -65,7 +63,38 @@ class Database(ModuleABC, OnReadyABC): 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') + 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') + break + + user = self._known_users.find_user_by_discord_id(u.id) + if user is not None: + break + + 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) + + results = self._servers.get_servers() + if results is None or len(results) == 0: + self._logger.error(__name__, f'Table Servers is empty!') + def _check_servers(self): + self._logger.debug(__name__, f'Start checking Servers table') for g in self._bot.guilds: g: discord.Guild = g try: @@ -91,6 +120,7 @@ class Database(ModuleABC, OnReadyABC): 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: @@ -120,6 +150,7 @@ class Database(ModuleABC, OnReadyABC): 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 @@ -154,6 +185,7 @@ class Database(ModuleABC, OnReadyABC): 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() -- 2.45.2 From 1d09ad80bfa609f8efe2f72f3669be4839bb86be Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 2 Dec 2021 18:07:43 +0100 Subject: [PATCH 11/48] Added UserJoinedServer model --- src/gismo_data/model/user.py | 12 +- src/gismo_data/model/user_joined_server.py | 132 +++++++++++++++++++++ 2 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 src/gismo_data/model/user_joined_server.py diff --git a/src/gismo_data/model/user.py b/src/gismo_data/model/user.py index 2fae830..3a02d06 100644 --- a/src/gismo_data/model/user.py +++ b/src/gismo_data/model/user.py @@ -7,11 +7,10 @@ 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): + def __init__(self, dc_id: int, xp: int, 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 @@ -34,10 +33,6 @@ class User(TableABC): 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""" @@ -45,10 +40,8 @@ class User(TableABC): `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`) ); """) @@ -77,11 +70,10 @@ class User(TableABC): def insert_string(self) -> str: return str(f""" INSERT INTO `Users` ( - `DiscordId`, `XP`, `ServerId`, `CreatedAt`, `LastModifiedAt` + `DiscordId`, `XP`, `CreatedAt`, `LastModifiedAt` ) VALUES ( {self._discord_id}, {self._xp}, - {self._server.server_id}, '{self._created_at}', '{self._modified_at}' ); diff --git a/src/gismo_data/model/user_joined_server.py b/src/gismo_data/model/user_joined_server.py new file mode 100644 index 0000000..b85a186 --- /dev/null +++ b/src/gismo_data/model/user_joined_server.py @@ -0,0 +1,132 @@ +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, server: Server, 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._server = server + 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 server(self) -> Server: + return self._server + + @property + def joined_on(self) -> datetime: + return self._joined_on + + @property + def leaved_on(self) -> datetime: + return self._leaved_on + + @staticmethod + def get_create_string() -> str: + return str(f""" + CREATE TABLE IF NOT EXISTS `UserJoinedServers` ( + `JoinId` BIGINT NOT NULL AUTO_INCREMENT, + `UserId` BIGINT NOT NULL, + `ServerId` BIGINT NOT NULL, + `JoinedOn` DATETIME(6) NOT NULL, + `LeavedOn` DATETIME(6), + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`), + FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`), + PRIMARY KEY(`ServerId`) + ); + """) + + @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; + """) + + @staticmethod + def get_select_by_server_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `UserJoinedServers` + WHERE `ServerId` = {id}; + """) + + @staticmethod + def get_select_active_by_server_id_string(id: int) -> str: + return str(f""" + SELECT * FROM `UserJoinedServers` + WHERE `ServerId` = {id} + AND `LeavedOn` IS NULL; + """) + @property + def insert_string(self) -> str: + return str(f""" + INSERT INTO `UserJoinedServers` ( + `UserId`, `ServerId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` + ) VALUES ( + {self._user.user_id}, + {self._server.server_id}, + {self._joined_on}, + {self._leaved_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} + AND `ServerId` = {self._server.server_id}; + """) + + @property + def delete_string(self) -> str: + return str(f""" + DELETE FROM `UserJoinedServers` + WHERE `Id` = {self._join_id}; + """) -- 2.45.2 From 22b0c3ca6afecdf6bb2c6f6262f547c99e17bb95 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Thu, 2 Dec 2021 18:08:19 +0100 Subject: [PATCH 12/48] Removed old imports --- src/gismo_data/model/user.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gismo_data/model/user.py b/src/gismo_data/model/user.py index 3a02d06..03236e4 100644 --- a/src/gismo_data/model/user.py +++ b/src/gismo_data/model/user.py @@ -1,9 +1,6 @@ from datetime import datetime -from typing import Optional from cpl_core.database import TableABC -from gismo_data.model.server import Server - class User(TableABC): -- 2.45.2 From d5de1991ebfb97bea53c90f272a14df3a30abf1a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 7 Dec 2021 15:16:39 +0100 Subject: [PATCH 13/48] Fixed loop and model handling --- src/gismo_data/model/user.py | 15 +++++++++++++-- src/gismo_data/model/user_joined_server.py | 22 ++++++++-------------- src/modules/database/database.py | 18 +++++++----------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/gismo_data/model/user.py b/src/gismo_data/model/user.py index 03236e4..2fae830 100644 --- a/src/gismo_data/model/user.py +++ b/src/gismo_data/model/user.py @@ -1,13 +1,17 @@ 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, created_at: datetime = None, modified_at: datetime = None, id=0): + 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 @@ -30,6 +34,10 @@ class User(TableABC): 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""" @@ -37,8 +45,10 @@ class User(TableABC): `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`) ); """) @@ -67,10 +77,11 @@ class User(TableABC): def insert_string(self) -> str: return str(f""" INSERT INTO `Users` ( - `DiscordId`, `XP`, `CreatedAt`, `LastModifiedAt` + `DiscordId`, `XP`, `ServerId`, `CreatedAt`, `LastModifiedAt` ) VALUES ( {self._discord_id}, {self._xp}, + {self._server.server_id}, '{self._created_at}', '{self._modified_at}' ); diff --git a/src/gismo_data/model/user_joined_server.py b/src/gismo_data/model/user_joined_server.py index b85a186..f0fe206 100644 --- a/src/gismo_data/model/user_joined_server.py +++ b/src/gismo_data/model/user_joined_server.py @@ -9,10 +9,9 @@ from gismo_data.model.server import Server class UserJoinedServer(TableABC): - def __init__(self, user: User, server: Server, joined_on: datetime, leaved_on: datetime=None, created_at: datetime=None, modified_at: datetime=None, id=0): + 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._server = server self._joined_on = joined_on self._leaved_on = leaved_on @@ -28,10 +27,6 @@ class UserJoinedServer(TableABC): def user(self) -> User: return self._user - @property - def server(self) -> Server: - return self._server - @property def joined_on(self) -> datetime: return self._joined_on @@ -46,14 +41,12 @@ class UserJoinedServer(TableABC): CREATE TABLE IF NOT EXISTS `UserJoinedServers` ( `JoinId` BIGINT NOT NULL AUTO_INCREMENT, `UserId` BIGINT NOT NULL, - `ServerId` BIGINT NOT NULL, `JoinedOn` DATETIME(6) NOT NULL, `LeavedOn` DATETIME(6), `CreatedAt` DATETIME(6), `LastModifiedAt` DATETIME(6), FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`), - FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`), - PRIMARY KEY(`ServerId`) + PRIMARY KEY(`JoinId`) ); """) @@ -89,24 +82,25 @@ class UserJoinedServer(TableABC): def get_select_by_server_id_string(id: int) -> str: return str(f""" SELECT * FROM `UserJoinedServers` - WHERE `ServerId` = {id}; + JOIN `Users` On `UserJoinedServers`.`UserId` = `Users`.`UserId` + WHERE `Users`.`ServerId` = {id}; """) @staticmethod def get_select_active_by_server_id_string(id: int) -> str: return str(f""" SELECT * FROM `UserJoinedServers` - WHERE `ServerId` = {id} - AND `LeavedOn` IS NULL; + JOIN `Users` On `UserJoinedServers`.`UserId` = `Users`.`UserId` + WHERE `Users`.`ServerId` = {id} + AND `UserJoinedServers`.`LeavedOn` IS NULL; """) @property def insert_string(self) -> str: return str(f""" INSERT INTO `UserJoinedServers` ( - `UserId`, `ServerId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` + `UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( {self._user.user_id}, - {self._server.server_id}, {self._joined_on}, {self._leaved_on}, '{self._created_at}', diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 7504f45..28e6104 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -64,17 +64,17 @@ class Database(ModuleABC, OnReadyABC): return def _check_known_users(self): - self._logger.debug(__name__, f'Start checking KnownUsers table') + 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') - break + continue user = self._known_users.find_user_by_discord_id(u.id) if user is not None: - break + continue self._logger.warn(__name__, f'Unknown user: {u.id}') self._logger.debug(__name__, f'Add user: {u.id}') @@ -88,10 +88,6 @@ class Database(ModuleABC, OnReadyABC): self._logger.debug(__name__, f'Added user: {u.id}') except Exception as e: self._logger.error(__name__, f'Cannot get user', 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_servers(self): self._logger.debug(__name__, f'Start checking Servers table') @@ -100,7 +96,7 @@ class Database(ModuleABC, OnReadyABC): try: server = self._servers.find_server_by_discord_id(g.id) if server is not None: - break + continue self._logger.warn(__name__, f'Server not found in database: {g.id}') self._logger.debug(__name__, f'Add server: {g.id}') @@ -130,7 +126,7 @@ class Database(ModuleABC, OnReadyABC): client = self._clients.find_client_by_server_id(server.server_id) if client is not None: - break + 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}') @@ -163,11 +159,11 @@ class Database(ModuleABC, OnReadyABC): u: discord.Member = u if u.bot: self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot') - break + continue user = self._users.find_user_by_discord_id(u.id) if user is not None: - break + continue self._logger.warn(__name__, f'User not found in database: {u.id}') self._logger.debug(__name__, f'Add user: {u.id}') -- 2.45.2 From ca361b63cb2936e1805e9ac9034d2b1a1f4bb7ae Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 7 Dec 2021 16:38:42 +0100 Subject: [PATCH 14/48] Added migration logic --- src/gismo/application.py | 4 ++ src/gismo/startup.py | 19 +++++- src/gismo_data/abc/migration_abc.py | 13 ++++ src/gismo_data/db_context.py | 4 -- src/gismo_data/migration/__init__.py | 1 + src/gismo_data/migration/initial_migration.py | 57 ++++++++++++++++ src/gismo_data/migration/migration_0_3.py | 65 +++++++++++++++++++ src/gismo_data/model/migration_history.py | 47 ++++++++++++++ src/gismo_data/service/migration_service.py | 43 ++++++++++++ 9 files changed, 247 insertions(+), 6 deletions(-) create mode 100644 src/gismo_data/abc/migration_abc.py create mode 100644 src/gismo_data/migration/__init__.py create mode 100644 src/gismo_data/migration/initial_migration.py create mode 100644 src/gismo_data/migration/migration_0_3.py create mode 100644 src/gismo_data/model/migration_history.py create mode 100644 src/gismo_data/service/migration_service.py diff --git a/src/gismo/application.py b/src/gismo/application.py index 9602da6..849c55e 100644 --- a/src/gismo/application.py +++ b/src/gismo/application.py @@ -3,8 +3,10 @@ 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): @@ -14,12 +16,14 @@ class Gismo(ApplicationABC): 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: diff --git a/src/gismo/startup.py b/src/gismo/startup.py index 307aa35..1e5e73e 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -15,12 +15,17 @@ 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_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.service.client_repository_service import ( ClientRepositoryABC, ClientRepositoryService) -from gismo_data.service.known_user_repository_service import KnownUserRepositoryService +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_repository_service import UserRepositoryService @@ -58,18 +63,28 @@ class Startup(StartupABC): 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) - + + # 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) provider: ServiceProviderABC = services.build_service_provider() diff --git a/src/gismo_data/abc/migration_abc.py b/src/gismo_data/abc/migration_abc.py new file mode 100644 index 0000000..53b1696 --- /dev/null +++ b/src/gismo_data/abc/migration_abc.py @@ -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 diff --git a/src/gismo_data/db_context.py b/src/gismo_data/db_context.py index aae38ca..c45dafa 100644 --- a/src/gismo_data/db_context.py +++ b/src/gismo_data/db_context.py @@ -16,10 +16,6 @@ class DBContext(DatabaseContext): 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") diff --git a/src/gismo_data/migration/__init__.py b/src/gismo_data/migration/__init__.py new file mode 100644 index 0000000..425ab6c --- /dev/null +++ b/src/gismo_data/migration/__init__.py @@ -0,0 +1 @@ +# imports diff --git a/src/gismo_data/migration/initial_migration.py b/src/gismo_data/migration/initial_migration.py new file mode 100644 index 0000000..b2882c5 --- /dev/null +++ b/src/gismo_data/migration/initial_migration.py @@ -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`;') diff --git a/src/gismo_data/migration/migration_0_3.py b/src/gismo_data/migration/migration_0_3.py new file mode 100644 index 0000000..138de96 --- /dev/null +++ b/src/gismo_data/migration/migration_0_3.py @@ -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`;') diff --git a/src/gismo_data/model/migration_history.py b/src/gismo_data/model/migration_history.py new file mode 100644 index 0000000..c00ba7a --- /dev/null +++ b/src/gismo_data/model/migration_history.py @@ -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}'; + """) diff --git a/src/gismo_data/service/migration_service.py b/src/gismo_data/service/migration_service.py new file mode 100644 index 0000000..cd34dd3 --- /dev/null +++ b/src/gismo_data/service/migration_service.py @@ -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) -- 2.45.2 From d1298606f3f776401c55f25b65690e897bdc18f5 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 7 Dec 2021 16:42:47 +0100 Subject: [PATCH 15/48] Removed get_create_table_string --- src/gismo_data/model/client.py | 19 ------------------- src/gismo_data/model/known_user.py | 12 ------------ src/gismo_data/model/server.py | 12 ------------ src/gismo_data/model/user.py | 15 --------------- src/gismo_data/model/user_joined_server.py | 15 --------------- .../service/known_user_repository_service.py | 2 -- 6 files changed, 75 deletions(-) diff --git a/src/gismo_data/model/client.py b/src/gismo_data/model/client.py index 9048ea4..61e6a6c 100644 --- a/src/gismo_data/model/client.py +++ b/src/gismo_data/model/client.py @@ -63,25 +63,6 @@ class Client(TableABC): def server(self) -> Server: return self._server - @staticmethod - def get_create_string() -> str: - return 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`) - ); - """) - @staticmethod def get_select_all_string() -> str: return str(f""" diff --git a/src/gismo_data/model/known_user.py b/src/gismo_data/model/known_user.py index 73ff562..7dcda21 100644 --- a/src/gismo_data/model/known_user.py +++ b/src/gismo_data/model/known_user.py @@ -23,18 +23,6 @@ class KnownUser(TableABC): def discord_id(self) -> int: return self._discord_id - @staticmethod - def get_create_string() -> str: - return 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`) - ); - """) - @staticmethod def get_select_all_string() -> str: return str(f""" diff --git a/src/gismo_data/model/server.py b/src/gismo_data/model/server.py index 5f9e9e5..14cddef 100644 --- a/src/gismo_data/model/server.py +++ b/src/gismo_data/model/server.py @@ -21,18 +21,6 @@ class Server(TableABC): @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: diff --git a/src/gismo_data/model/user.py b/src/gismo_data/model/user.py index 2fae830..f133f1a 100644 --- a/src/gismo_data/model/user.py +++ b/src/gismo_data/model/user.py @@ -38,21 +38,6 @@ class User(TableABC): 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""" diff --git a/src/gismo_data/model/user_joined_server.py b/src/gismo_data/model/user_joined_server.py index f0fe206..5c6f13e 100644 --- a/src/gismo_data/model/user_joined_server.py +++ b/src/gismo_data/model/user_joined_server.py @@ -34,21 +34,6 @@ class UserJoinedServer(TableABC): @property def leaved_on(self) -> datetime: return self._leaved_on - - @staticmethod - def get_create_string() -> str: - return 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`) - ); - """) @staticmethod def get_select_all_string() -> str: diff --git a/src/gismo_data/service/known_user_repository_service.py b/src/gismo_data/service/known_user_repository_service.py index d349ea5..d85b44c 100644 --- a/src/gismo_data/service/known_user_repository_service.py +++ b/src/gismo_data/service/known_user_repository_service.py @@ -65,8 +65,6 @@ class KnownUserRepositoryService(KnownUserRepositoryABC): result[1], result[2], result[3], - result[4], - self._servers.get_server_by_id(result[3]), id=result[0] ) -- 2.45.2 From 5fce7318ae261b1783911868607f963bd3b6b935 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 7 Dec 2021 16:53:03 +0100 Subject: [PATCH 16/48] Removed unused sql statement --- src/gismo_data/model/user_joined_server.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gismo_data/model/user_joined_server.py b/src/gismo_data/model/user_joined_server.py index 5c6f13e..4c87262 100644 --- a/src/gismo_data/model/user_joined_server.py +++ b/src/gismo_data/model/user_joined_server.py @@ -99,8 +99,7 @@ class UserJoinedServer(TableABC): UPDATE `UserJoinedServers` SET `LeavedOn` = {self._leaved_on}, `LastModifiedAt` = '{self._modified_at}' - WHERE `UserId` = {self._user.user_id} - AND `ServerId` = {self._server.server_id}; + WHERE `UserId` = {self._user.user_id}; """) @property -- 2.45.2 From e73ebeb052996e4d073f545fee24141b36c3b201 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 7 Dec 2021 17:15:13 +0100 Subject: [PATCH 17/48] Added UserJoinedServer Repo --- src/gismo/startup.py | 3 + .../abc/user_joined_server_repository_abc.py | 35 ++++++ src/gismo_data/model/user_joined_server.py | 16 --- .../user_joined_server_repository_service.py | 111 ++++++++++++++++++ .../service/user_repository_service.py | 3 + 5 files changed, 152 insertions(+), 16 deletions(-) create mode 100644 src/gismo_data/abc/user_joined_server_repository_abc.py create mode 100644 src/gismo_data/service/user_joined_server_repository_service.py diff --git a/src/gismo/startup.py b/src/gismo/startup.py index 1e5e73e..223262a 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -17,6 +17,7 @@ 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_repository_abc import UserRepositoryABC from gismo_data.db_context import DBContext from gismo_data.migration.initial_migration import InitialMigration @@ -28,6 +29,7 @@ from gismo_data.service.known_user_repository_service import \ 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_repository_service import UserRepositoryService from modules.base.base import Base from modules.boot_log.boot_log import BootLog @@ -76,6 +78,7 @@ class Startup(StartupABC): services.add_transient(UserRepositoryABC, UserRepositoryService) services.add_transient(ClientRepositoryABC, ClientRepositoryService) services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService) + services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService) # modules services.add_transient(ModuleABC, Database) diff --git a/src/gismo_data/abc/user_joined_server_repository_abc.py b/src/gismo_data/abc/user_joined_server_repository_abc.py new file mode 100644 index 0000000..49b8b7f --- /dev/null +++ b/src/gismo_data/abc/user_joined_server_repository_abc.py @@ -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_server_by_user_id(self, user_id: int) -> 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 diff --git a/src/gismo_data/model/user_joined_server.py b/src/gismo_data/model/user_joined_server.py index 4c87262..b31b527 100644 --- a/src/gismo_data/model/user_joined_server.py +++ b/src/gismo_data/model/user_joined_server.py @@ -63,22 +63,6 @@ class UserJoinedServer(TableABC): AND `LeavedOn` IS NULL; """) - @staticmethod - def get_select_by_server_id_string(id: int) -> str: - return str(f""" - SELECT * FROM `UserJoinedServers` - JOIN `Users` On `UserJoinedServers`.`UserId` = `Users`.`UserId` - WHERE `Users`.`ServerId` = {id}; - """) - - @staticmethod - def get_select_active_by_server_id_string(id: int) -> str: - return str(f""" - SELECT * FROM `UserJoinedServers` - JOIN `Users` On `UserJoinedServers`.`UserId` = `Users`.`UserId` - WHERE `Users`.`ServerId` = {id} - AND `UserJoinedServers`.`LeavedOn` IS NULL; - """) @property def insert_string(self) -> str: return str(f""" diff --git a/src/gismo_data/service/user_joined_server_repository_service.py b/src/gismo_data/service/user_joined_server_repository_service.py new file mode 100644 index 0000000..786ef57 --- /dev/null +++ b/src/gismo_data/service/user_joined_server_repository_service.py @@ -0,0 +1,111 @@ +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) -> List[UserJoinedServer]: + joins = List(UserJoinedServer) + self._logger.trace(__name__, f'Send SQL command: {UserJoinedServer.get_select_by_id_string(id)}') + results = self._context.select(UserJoinedServer.get_select_by_id_string(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_user_joined_server_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) diff --git a/src/gismo_data/service/user_repository_service.py b/src/gismo_data/service/user_repository_service.py index 6854313..2644dfc 100644 --- a/src/gismo_data/service/user_repository_service.py +++ b/src/gismo_data/service/user_repository_service.py @@ -46,6 +46,9 @@ class UserRepositoryService(UserRepositoryABC): 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] + + result = result[0] + return User( result[1], result[2], -- 2.45.2 From 9bae6c3c130339411075ba7c6dafe7e8062e0172 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 7 Dec 2021 17:36:19 +0100 Subject: [PATCH 18/48] Improved database on_ready --- src/gismo_data/model/user_joined_server.py | 34 ++++++++++----- src/modules/database/database.py | 49 +++++++++++++++++++++- 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/gismo_data/model/user_joined_server.py b/src/gismo_data/model/user_joined_server.py index b31b527..be73141 100644 --- a/src/gismo_data/model/user_joined_server.py +++ b/src/gismo_data/model/user_joined_server.py @@ -65,17 +65,29 @@ class UserJoinedServer(TableABC): @property def insert_string(self) -> str: - 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}' - ); - """) + 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: diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 28e6104..431a62e 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -4,14 +4,18 @@ 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_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_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.service.user_repository_service import ServerRepositoryABC from modules_core.abc.events.on_ready_abc import OnReadyABC from modules_core.abc.module_abc import ModuleABC @@ -28,7 +32,8 @@ class Database(ModuleABC, OnReadyABC): server_repo: ServerRepositoryABC, user_repo: UserRepositoryABC, client_repo: ClientRepositoryABC, - known_users: KnownUserRepositoryABC + known_users: KnownUserRepositoryABC, + user_joins: UserJoinedServerRepositoryABC ): self._config = config @@ -39,7 +44,8 @@ class Database(ModuleABC, OnReadyABC): self._users = user_repo self._clients = client_repo self._known_users = known_users - + self._user_joins = user_joins + ModuleABC.__init__(self) self._priorities[OnReadyABC] = 0 self._logger.trace(__name__, f'Module {type(self)} loaded') @@ -178,6 +184,44 @@ class Database(ModuleABC, OnReadyABC): 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 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: 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(u.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: {g.id}:{u.id}@{m.joined_at}') + self._logger.debug(__name__, f'Add UserJoinedServer: {g.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!') + async def on_ready(self): self._logger.debug(__name__, f'Module {type(self)} started') @@ -185,6 +229,7 @@ class Database(ModuleABC, OnReadyABC): self._check_servers() self._check_clients() self._check_users() + self._check_user_joins() self._validate_init_time() self._logger.trace(__name__, f'Module {type(self)} stopped') -- 2.45.2 From f03ee54703520cea349e2811cbf9cb29f31a25bc Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 07:14:50 +0100 Subject: [PATCH 19/48] Added find function to client repo --- src/gismo_data/abc/client_repository_abc.py | 5 ++++- src/gismo_data/model/client.py | 8 ++++++++ .../service/client_repository_service.py | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/gismo_data/abc/client_repository_abc.py b/src/gismo_data/abc/client_repository_abc.py index 6b1dcdb..2c84839 100644 --- a/src/gismo_data/abc/client_repository_abc.py +++ b/src/gismo_data/abc/client_repository_abc.py @@ -23,7 +23,10 @@ class ClientRepositoryABC(ABC): def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: pass @abstractmethod - def find_client_by_server_id(self, discord_id: int) -> Optional[Client]: pass + 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 diff --git a/src/gismo_data/model/client.py b/src/gismo_data/model/client.py index 61e6a6c..dd918a6 100644 --- a/src/gismo_data/model/client.py +++ b/src/gismo_data/model/client.py @@ -90,6 +90,14 @@ class Client(TableABC): 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""" diff --git a/src/gismo_data/service/client_repository_service.py b/src/gismo_data/service/client_repository_service.py index 8f0f5a1..1397ec9 100644 --- a/src/gismo_data/service/client_repository_service.py +++ b/src/gismo_data/service/client_repository_service.py @@ -102,6 +102,25 @@ class ClientRepositoryService(ClientRepositoryABC): 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_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 add_client(self, client: Client): self._logger.trace(__name__, f'Send SQL command: {client.insert_string}') -- 2.45.2 From e34fbb60aa08e3bc29d41372fba3ed81fd4639f7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 07:36:54 +0100 Subject: [PATCH 20/48] Added logic to append received messages --- src/gismo_data/abc/client_repository_abc.py | 3 ++ src/gismo_data/model/client.py | 29 +++++++++++++++++-- .../service/client_repository_service.py | 18 ++++++++++-- .../user_joined_server_repository_service.py | 2 +- .../service/user_repository_service.py | 5 ++-- src/modules/base/base.py | 28 ++++++++++++++++-- 6 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/gismo_data/abc/client_repository_abc.py b/src/gismo_data/abc/client_repository_abc.py index 2c84839..53e0c31 100644 --- a/src/gismo_data/abc/client_repository_abc.py +++ b/src/gismo_data/abc/client_repository_abc.py @@ -36,3 +36,6 @@ class ClientRepositoryABC(ABC): @abstractmethod def delete_client(self, client: Client): pass + + @abstractmethod + def apppend_received_message_count(self, id: int, server_id: int, value: int): pass diff --git a/src/gismo_data/model/client.py b/src/gismo_data/model/client.py index dd918a6..0382cfc 100644 --- a/src/gismo_data/model/client.py +++ b/src/gismo_data/model/client.py @@ -43,22 +43,47 @@ class Client(TableABC): 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 @@ -134,12 +159,12 @@ class Client(TableABC): `ReceivedCommandsCount` = {self._received_command_count}, `MovedUsersCount` = {self._moved_users_count}, `LastModifiedAt` = '{self._modified_at}' - WHERE `Id` = {self._client_id}; + WHERE `ClientId` = {self._client_id}; """) @property def delete_string(self) -> str: return str(f""" DELETE FROM `Clients` - WHERE `Id` = {self._client_id}; + WHERE `ClientId` = {self._client_id}; """) diff --git a/src/gismo_data/service/client_repository_service.py b/src/gismo_data/service/client_repository_service.py index 1397ec9..9d297c6 100644 --- a/src/gismo_data/service/client_repository_service.py +++ b/src/gismo_data/service/client_repository_service.py @@ -104,8 +104,8 @@ class ClientRepositoryService(ClientRepositoryABC): ) 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_server_id_string(discord_id)}') - result = self._context.select(Client.get_select_by_server_id_string(discord_id)) + 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 @@ -133,3 +133,17 @@ class ClientRepositoryService(ClientRepositoryABC): 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 apppend_received_message_count(self, id: int, server_id: int, value: int): + 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') + + client.received_message_count += 1 + self.update_client(client) diff --git a/src/gismo_data/service/user_joined_server_repository_service.py b/src/gismo_data/service/user_joined_server_repository_service.py index 786ef57..91fcbed 100644 --- a/src/gismo_data/service/user_joined_server_repository_service.py +++ b/src/gismo_data/service/user_joined_server_repository_service.py @@ -86,7 +86,7 @@ class UserJoinedServerRepositoryService(UserJoinedServerRepositoryABC): 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( diff --git a/src/gismo_data/service/user_repository_service.py b/src/gismo_data/service/user_repository_service.py index 2644dfc..ba857be 100644 --- a/src/gismo_data/service/user_repository_service.py +++ b/src/gismo_data/service/user_repository_service.py @@ -35,7 +35,8 @@ class UserRepositoryService(UserRepositoryABC): 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)) + result = self._context.select(User.get_select_by_id_string(id))[0] + return User( result[1], result[2], @@ -47,8 +48,6 @@ class UserRepositoryService(UserRepositoryABC): 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] - result = result[0] - return User( result[1], result[2], diff --git a/src/modules/base/base.py b/src/modules/base/base.py index 530b3cd..79a4589 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -1,17 +1,33 @@ import discord +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_data.abc.client_repository_abc import ClientRepositoryABC +from gismo_data.abc.server_repository_abc import ServerRepositoryABC from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC 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.events.on_voice_state_update_abc import \ + OnVoiceStateUpdateABC from modules_core.abc.module_abc import ModuleABC class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): - def __init__(self, logger: LoggerABC): + def __init__( + self, + logger: LoggerABC, + clients: ClientRepositoryABC, + servers: ServerRepositoryABC, + bot: BotServiceABC, + db: DatabaseContextABC + ): self._logger = logger + self._clients = clients + self._servers = servers + self._bot = bot + self._db = db ModuleABC.__init__(self) self._priorities[OnMemberJoinABC] = 1 @@ -19,10 +35,18 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): 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}') + async def on_member_join(self, member: discord.Member): self._logger.debug(__name__, f'Module {type(self)} started') async def on_message(self, message: discord.Message): + self._apppend_received_message_count(message.guild.id) self._logger.debug(__name__, f'Module {type(self)} started') async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): -- 2.45.2 From be5567c1fd9d65f00ddac3ed36572fbe64c40472 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 07:41:09 +0100 Subject: [PATCH 21/48] Added helper functions to append client values --- src/gismo_data/abc/client_repository_abc.py | 12 +++++++++ .../service/client_repository_service.py | 26 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/gismo_data/abc/client_repository_abc.py b/src/gismo_data/abc/client_repository_abc.py index 53e0c31..4c61661 100644 --- a/src/gismo_data/abc/client_repository_abc.py +++ b/src/gismo_data/abc/client_repository_abc.py @@ -37,5 +37,17 @@ class ClientRepositoryABC(ABC): @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 diff --git a/src/gismo_data/service/client_repository_service.py b/src/gismo_data/service/client_repository_service.py index 9d297c6..cb38dd5 100644 --- a/src/gismo_data/service/client_repository_service.py +++ b/src/gismo_data/service/client_repository_service.py @@ -134,7 +134,7 @@ class ClientRepositoryService(ClientRepositoryABC): self._logger.trace(__name__, f'Send SQL command: {client.delete_string}') self._context.cursor.execute(client.delete_string) - def apppend_received_message_count(self, id: int, server_id: int, value: int): + 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}') @@ -145,5 +145,27 @@ class ClientRepositoryService(ClientRepositoryABC): self._logger.warn(__name__, f'Cannot find client by ids {id}@{server.server_id}') raise Exception('Value not found') - client.received_message_count += 1 + 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) -- 2.45.2 From 68c1bc0bc3b8fbc15b9b66ff42b6522f5425869c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 07:48:55 +0100 Subject: [PATCH 22/48] Added logic to save client data --- src/gismo_core/service/message_service.py | 15 ++++++++++++++- src/modules/base/base.py | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/gismo_core/service/message_service.py b/src/gismo_core/service/message_service.py index 32ae1c3..a4156d3 100644 --- a/src/gismo_core/service/message_service.py +++ b/src/gismo_core/service/message_service.py @@ -3,6 +3,7 @@ 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 @@ -10,14 +11,17 @@ 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): + 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') @@ -29,11 +33,14 @@ class MessageService(MessageServiceABC): 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) + self._db.save_changes() self._logger.info(__name__, f'Deleted message {message}') async def send_channel_message(self, channel: discord.TextChannel, message: str): @@ -45,6 +52,8 @@ class MessageService(MessageServiceABC): 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) + self._db.save_changes() await self.delete_message(msg) async def send_dm_message(self, message: str, receiver: Union[discord.User, discord.Member]): @@ -54,6 +63,8 @@ class MessageService(MessageServiceABC): 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) + 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]): @@ -73,4 +84,6 @@ class MessageService(MessageServiceABC): 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) + self._db.save_changes() await self.delete_message(msg) diff --git a/src/modules/base/base.py b/src/modules/base/base.py index 79a4589..0e315ee 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -42,6 +42,13 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): 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}') + async def on_member_join(self, member: discord.Member): self._logger.debug(__name__, f'Module {type(self)} started') -- 2.45.2 From e3ac78f97bd6ac0a2f29b295614a44a7cb65e370 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 07:49:52 +0100 Subject: [PATCH 23/48] Fixed argument error --- src/gismo_core/service/message_service.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gismo_core/service/message_service.py b/src/gismo_core/service/message_service.py index a4156d3..b86a712 100644 --- a/src/gismo_core/service/message_service.py +++ b/src/gismo_core/service/message_service.py @@ -39,7 +39,7 @@ class MessageService(MessageServiceABC): 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) + 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}') @@ -52,7 +52,7 @@ class MessageService(MessageServiceABC): 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) + self._clients.apppend_sent_message_count(self._bot.user.id, channel.guild.id, 1) self._db.save_changes() await self.delete_message(msg) @@ -63,7 +63,7 @@ class MessageService(MessageServiceABC): 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) + 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}') @@ -84,6 +84,6 @@ class MessageService(MessageServiceABC): 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) + self._clients.apppend_sent_message_count(self._bot.user.id, ctx.guild.id, 1) self._db.save_changes() await self.delete_message(msg) -- 2.45.2 From a10724a4950ba8091e44123b686ba2f090636f1a Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 07:50:35 +0100 Subject: [PATCH 24/48] Fixed return error --- src/gismo_data/service/client_repository_service.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gismo_data/service/client_repository_service.py b/src/gismo_data/service/client_repository_service.py index cb38dd5..fc2b9e7 100644 --- a/src/gismo_data/service/client_repository_service.py +++ b/src/gismo_data/service/client_repository_service.py @@ -144,6 +144,8 @@ class ClientRepositoryService(ClientRepositoryABC): 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) -- 2.45.2 From f417eca64456413689a683878529661352a7c60e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 17:32:55 +0100 Subject: [PATCH 25/48] Added check for known user at on_member_join --- src/modules/base/base.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/modules/base/base.py b/src/modules/base/base.py index 0e315ee..c05a1df 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -1,10 +1,14 @@ +from typing import Union + import discord 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_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.model.known_user import KnownUser from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC from modules_core.abc.events.on_message_abc import OnMessageABC from modules_core.abc.events.on_voice_state_update_abc import \ @@ -19,6 +23,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): logger: LoggerABC, clients: ClientRepositoryABC, servers: ServerRepositoryABC, + known_users: KnownUserRepositoryABC, bot: BotServiceABC, db: DatabaseContextABC ): @@ -26,6 +31,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): self._logger = logger self._clients = clients self._servers = servers + self._known_users = known_users self._bot = bot self._db = db @@ -49,7 +55,22 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): except Exception as e: self._logger.error(__name__, f'Cannot edit client {self._bot.user.id}@{g_id}') - async def on_member_join(self, member: discord.Member): + 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}') + + async def on_member_join(self, member: Union[discord.User, discord.Member]): + self._check_for_known_user(member) + # self._check_for_user(member) self._logger.debug(__name__, f'Module {type(self)} started') async def on_message(self, message: discord.Message): @@ -57,4 +78,6 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): self._logger.debug(__name__, f'Module {type(self)} started') async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): + # todo: save ontime + # todo: add xp to user when he goes offline self._logger.debug(__name__, f'Module {type(self)} started') -- 2.45.2 From 9d17070d0261ebfd1aaf6dc708c604e4d66105d8 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 17:40:50 +0100 Subject: [PATCH 26/48] Fixed user repo error --- src/gismo_data/abc/user_repository_abc.py | 7 ++++-- src/gismo_data/model/user.py | 8 +++++++ .../service/user_repository_service.py | 24 ++++++++++++++----- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/gismo_data/abc/user_repository_abc.py b/src/gismo_data/abc/user_repository_abc.py index c198753..5a647f0 100644 --- a/src/gismo_data/abc/user_repository_abc.py +++ b/src/gismo_data/abc/user_repository_abc.py @@ -18,10 +18,13 @@ class UserRepositoryABC(ABC): def get_user_by_id(self, id: int) -> User: pass @abstractmethod - def get_user_by_discord_id(self, discord_id: int) -> User: pass + def get_users_by_discord_id(self, discord_id: int) -> List[User]: pass @abstractmethod - def find_user_by_discord_id(self, discord_id: int) -> Optional[User]: pass + 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 diff --git a/src/gismo_data/model/user.py b/src/gismo_data/model/user.py index f133f1a..5597c07 100644 --- a/src/gismo_data/model/user.py +++ b/src/gismo_data/model/user.py @@ -58,6 +58,14 @@ class User(TableABC): 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""" diff --git a/src/gismo_data/service/user_repository_service.py b/src/gismo_data/service/user_repository_service.py index ba857be..7bb29ec 100644 --- a/src/gismo_data/service/user_repository_service.py +++ b/src/gismo_data/service/user_repository_service.py @@ -43,10 +43,22 @@ class UserRepositoryService(UserRepositoryABC): self._servers.get_server_by_id(result[3]), id=result[0] ) - - def get_user_by_discord_id(self, discord_id: int) -> User: + + 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)}') - result = self._context.select(User.get_select_by_discord_id_string(discord_id))[0] + 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], @@ -55,9 +67,9 @@ class UserRepositoryService(UserRepositoryABC): 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)) + 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 -- 2.45.2 From 4955eb3a19491360b06c9b595c7705fb384f1b13 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 17:42:21 +0100 Subject: [PATCH 27/48] Fixed database module --- src/modules/database/database.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 431a62e..b7fb766 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -1,3 +1,4 @@ +from ctypes import Union from datetime import datetime import discord @@ -162,12 +163,12 @@ class Database(ModuleABC, OnReadyABC): self._logger.fatal(__name__, f'Server not found in database: {g.id}') for u in g.members: - u: discord.Member = u + 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(u.id) + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id) if user is not None: continue -- 2.45.2 From c6e52039cb1199c1e3c462f03023350600cefdc9 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 17:45:05 +0100 Subject: [PATCH 28/48] Fixed database module --- src/modules/database/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index b7fb766..4e2910c 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -201,7 +201,7 @@ class Database(ModuleABC, OnReadyABC): self._logger.trace(__name__, f'User {u.id} is ignored, because its a bot') continue - user = self._users.find_user_by_discord_id(u.id) + 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}') -- 2.45.2 From adc74d6288afe4e07fa3ece1b02df04936e31feb Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 17:59:22 +0100 Subject: [PATCH 29/48] Fixed server repo --- src/gismo_data/service/server_repository_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gismo_data/service/server_repository_service.py b/src/gismo_data/service/server_repository_service.py index cac5685..6096390 100644 --- a/src/gismo_data/service/server_repository_service.py +++ b/src/gismo_data/service/server_repository_service.py @@ -37,7 +37,7 @@ class ServerRepositoryService(ServerRepositoryABC): 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)) + result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0] return Server( result[1], id=result[0] -- 2.45.2 From 199c269804894067814930334cfe0f2772e7229f Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 18:26:51 +0100 Subject: [PATCH 30/48] Added logic to handle on_member_join & remove --- src/gismo_data/model/user_joined_server.py | 12 +++- src/modules/base/base.py | 77 ++++++++++++++++++++-- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/gismo_data/model/user_joined_server.py b/src/gismo_data/model/user_joined_server.py index be73141..7ec4806 100644 --- a/src/gismo_data/model/user_joined_server.py +++ b/src/gismo_data/model/user_joined_server.py @@ -31,9 +31,19 @@ class UserJoinedServer(TableABC): 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: @@ -93,7 +103,7 @@ class UserJoinedServer(TableABC): def udpate_string(self) -> str: return str(f""" UPDATE `UserJoinedServers` - SET `LeavedOn` = {self._leaved_on}, + SET `LeavedOn` = '{self._leaved_on}', `LastModifiedAt` = '{self._modified_at}' WHERE `UserId` = {self._user.user_id}; """) diff --git a/src/modules/base/base.py b/src/modules/base/base.py index c05a1df..5522cf2 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -1,3 +1,4 @@ +from datetime import datetime from typing import Union import discord @@ -5,18 +6,25 @@ 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_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_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 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, OnMessageABC, OnVoiceStateUpdateABC): +class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceStateUpdateABC): def __init__( self, @@ -24,19 +32,26 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): clients: ClientRepositoryABC, servers: ServerRepositoryABC, known_users: KnownUserRepositoryABC, + users: UserRepositoryABC, + user_joins: UserJoinedServerRepositoryABC, bot: BotServiceABC, - db: DatabaseContextABC + db: DatabaseContextABC, + messenger: MessageServiceABC ): self._logger = logger self._clients = clients self._servers = servers self._known_users = known_users + self._users = users + self._user_joins = user_joins 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') @@ -66,18 +81,66 @@ class Base(ModuleABC, OnMemberJoinABC, OnMessageABC, OnVoiceStateUpdateABC): 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}') + 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}') + # todo content to config + await self._messenger.send_dm_message(f'Welcome to {member.guild.name}', 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 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}') + # todo content to config + await self._messenger.send_dm_message(f'Bye bye', 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) async def on_member_join(self, member: Union[discord.User, discord.Member]): - self._check_for_known_user(member) - # self._check_for_user(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._apppend_received_message_count(message.guild.id) 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) 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') # todo: save ontime # todo: add xp to user when he goes offline - self._logger.debug(__name__, f'Module {type(self)} started') -- 2.45.2 From 49aa2f3aa33c11c00d4620cf77a2cb00a43ca1e7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 18:34:32 +0100 Subject: [PATCH 31/48] Put welcome and goodbye messages into config --- src/gismo_core/configuration/server_settings.py | 12 ++++++++++++ src/modules/base/base.py | 13 ++++++++----- src/modules/database/database.py | 2 ++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/gismo_core/configuration/server_settings.py b/src/gismo_core/configuration/server_settings.py index f339b9c..c298cb8 100644 --- a/src/gismo_core/configuration/server_settings.py +++ b/src/gismo_core/configuration/server_settings.py @@ -13,6 +13,8 @@ class ServerSettings(ConfigurationModelABC): self._message_delete_timer: int = 0 self._login_message_channel_id: int = 0 self._login_message: str = '' + self._welcome_message: str = '' + self._goodbye_message: str = '' @property def id(self) -> str: @@ -30,12 +32,22 @@ class ServerSettings(ConfigurationModelABC): def login_message(self) -> str: return self._login_message + @property + def welcome_message(self) -> str: + return self._welcome_message + + @property + def goodbye_message(self) -> str: + return self._goodbye_message + 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._goodbye_message = settings['GoodbyeMessage'] except Exception as e: Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings') Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/modules/base/base.py b/src/modules/base/base.py index 5522cf2..5d233ef 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -2,11 +2,13 @@ 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 @@ -28,6 +30,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS def __init__( self, + config: ConfigurationABC, logger: LoggerABC, clients: ClientRepositoryABC, servers: ServerRepositoryABC, @@ -38,7 +41,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS db: DatabaseContextABC, messenger: MessageServiceABC ): - + self._config = config self._logger = logger self._clients = clients self._servers = servers @@ -85,8 +88,8 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS async def _add_if_not_exists_user(self, member: Union[discord.User, discord.Member]): self._logger.debug(__name__, f'Check if user exists {member}') - # todo content to config - await self._messenger.send_dm_message(f'Welcome to {member.guild.name}', 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) try: server = self._servers.get_server_by_discord_id(member.guild.id) @@ -107,8 +110,8 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS async def _remove_user(self, member: Union[discord.User, discord.Member]): self._logger.debug(__name__, f'Remove user {member}') - # todo content to config - await self._messenger.send_dm_message(f'Bye bye', 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) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 4e2910c..6cdb2fb 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -222,6 +222,8 @@ class Database(ModuleABC, OnReadyABC): results = self._users.get_users() if results is None or len(results) == 0: self._logger.error(__name__, f'Table Users is empty!') + + # todo check for users that arent on the server anymore async def on_ready(self): self._logger.debug(__name__, f'Module {type(self)} started') -- 2.45.2 From 789186454e756dd0f45419d766f87150da995ce7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 18:35:31 +0100 Subject: [PATCH 32/48] Removed comment --- src/modules/database/database.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 6cdb2fb..4e2910c 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -222,8 +222,6 @@ class Database(ModuleABC, OnReadyABC): results = self._users.get_users() if results is None or len(results) == 0: self._logger.error(__name__, f'Table Users is empty!') - - # todo check for users that arent on the server anymore async def on_ready(self): self._logger.debug(__name__, f'Module {type(self)} started') -- 2.45.2 From 7e6485459b64837eca0c605555b49cb5cec3675b Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 18:42:52 +0100 Subject: [PATCH 33/48] Fixed user_joined_server repo --- .../abc/user_joined_server_repository_abc.py | 2 +- .../user_joined_server_repository_service.py | 26 ++++++++----------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/gismo_data/abc/user_joined_server_repository_abc.py b/src/gismo_data/abc/user_joined_server_repository_abc.py index 49b8b7f..55de271 100644 --- a/src/gismo_data/abc/user_joined_server_repository_abc.py +++ b/src/gismo_data/abc/user_joined_server_repository_abc.py @@ -17,7 +17,7 @@ class UserJoinedServerRepositoryABC(ABC): def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer: pass @abstractmethod - def get_user_joined_server_by_user_id(self, user_id: int) -> UserJoinedServer: pass + 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 diff --git a/src/gismo_data/service/user_joined_server_repository_service.py b/src/gismo_data/service/user_joined_server_repository_service.py index 91fcbed..3cb5311 100644 --- a/src/gismo_data/service/user_joined_server_repository_service.py +++ b/src/gismo_data/service/user_joined_server_repository_service.py @@ -37,23 +37,19 @@ class UserJoinedServerRepositoryService(UserJoinedServerRepositoryABC): return joins - def get_user_joined_server_by_id(self, id: int) -> List[UserJoinedServer]: - joins = List(UserJoinedServer) + 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)}') - results = self._context.select(UserJoinedServer.get_select_by_id_string(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 + 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_server_by_user_id(self, user_id: int) -> List[UserJoinedServer]: + 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)) -- 2.45.2 From f800a11f41c789d1376925a9512c9d0ad186b536 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 18:53:25 +0100 Subject: [PATCH 34/48] Added logic to check in db if user already left before starting --- src/modules/database/database.py | 39 ++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 4e2910c..f655506 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -187,15 +187,15 @@ class Database(ModuleABC, OnReadyABC): def _check_user_joins(self): self._logger.debug(__name__, f'Start checking UserJoinedServers table') - for g in self._bot.guilds: - g: discord.Guild = g + for guild in self._bot.guilds: + guild: discord.Guild = guild - 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: + 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') @@ -210,8 +210,8 @@ class Database(ModuleABC, OnReadyABC): continue m: discord.Member = u - self._logger.warn(__name__, f'Active UserJoinedServer not found in database: {g.id}:{u.id}@{m.joined_at}') - self._logger.debug(__name__, f'Add UserJoinedServer: {g.id}:{u.id}@{m.joined_at}') + 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() @@ -223,6 +223,24 @@ class Database(ModuleABC, OnReadyABC): 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() + async def on_ready(self): self._logger.debug(__name__, f'Module {type(self)} started') @@ -234,3 +252,4 @@ class Database(ModuleABC, OnReadyABC): self._validate_init_time() self._logger.trace(__name__, f'Module {type(self)} stopped') + exit() -- 2.45.2 From 0b17b27bd01e085bcb38ebd1e10d81554c3b2e17 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 19:00:22 +0100 Subject: [PATCH 35/48] Removed debug exit --- src/modules/database/database.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index f655506..a89c84d 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -252,4 +252,3 @@ class Database(ModuleABC, OnReadyABC): self._validate_init_time() self._logger.trace(__name__, f'Module {type(self)} stopped') - exit() -- 2.45.2 From 291efd23192f71741e07d97fb2eb2495997d550c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 19:07:52 +0100 Subject: [PATCH 36/48] Build project --- src/gismo_data/__init__.py | 24 ++++++++++++++++++++++++ src/gismo_data/abc/__init__.py | 24 ++++++++++++++++++++++++ src/gismo_data/migration/__init__.py | 24 ++++++++++++++++++++++++ src/gismo_data/model/__init__.py | 24 ++++++++++++++++++++++++ src/gismo_data/service/__init__.py | 24 ++++++++++++++++++++++++ 5 files changed, 120 insertions(+) diff --git a/src/gismo_data/__init__.py b/src/gismo_data/__init__.py index 425ab6c..18b850e 100644 --- a/src/gismo_data/__init__.py +++ b/src/gismo_data/__init__.py @@ -1 +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.2.0' + +from collections import namedtuple + # imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='2', micro='0') diff --git a/src/gismo_data/abc/__init__.py b/src/gismo_data/abc/__init__.py index 425ab6c..87b802e 100644 --- a/src/gismo_data/abc/__init__.py +++ b/src/gismo_data/abc/__init__.py @@ -1 +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.2.0' + +from collections import namedtuple + # imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='2', micro='0') diff --git a/src/gismo_data/migration/__init__.py b/src/gismo_data/migration/__init__.py index 425ab6c..49a2557 100644 --- a/src/gismo_data/migration/__init__.py +++ b/src/gismo_data/migration/__init__.py @@ -1 +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.2.0' + +from collections import namedtuple + # imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='2', micro='0') diff --git a/src/gismo_data/model/__init__.py b/src/gismo_data/model/__init__.py index 425ab6c..f45fb29 100644 --- a/src/gismo_data/model/__init__.py +++ b/src/gismo_data/model/__init__.py @@ -1 +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.2.0' + +from collections import namedtuple + # imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='2', micro='0') diff --git a/src/gismo_data/service/__init__.py b/src/gismo_data/service/__init__.py index 425ab6c..67ad80d 100644 --- a/src/gismo_data/service/__init__.py +++ b/src/gismo_data/service/__init__.py @@ -1 +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.2.0' + +from collections import namedtuple + # imports + +VersionInfo = namedtuple('VersionInfo', 'major minor micro') +version_info = VersionInfo(major='0', minor='2', micro='0') -- 2.45.2 From 51fd8f7a8b7f3ba544184fd37f38ea3ef7072e33 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 19:08:20 +0100 Subject: [PATCH 37/48] Build with new version --- src/gismo/__init__.py | 4 ++-- src/gismo/gismo.json | 2 +- src/gismo_core/__init__.py | 4 ++-- src/gismo_core/abc/__init__.py | 4 ++-- src/gismo_core/configuration/__init__.py | 4 ++-- src/gismo_core/service/__init__.py | 4 ++-- src/gismo_data/__init__.py | 4 ++-- src/gismo_data/abc/__init__.py | 4 ++-- src/gismo_data/migration/__init__.py | 4 ++-- src/gismo_data/model/__init__.py | 4 ++-- src/gismo_data/service/__init__.py | 4 ++-- src/modules/boot_log/__init__.py | 4 ++-- src/modules_core/__init__.py | 4 ++-- src/modules_core/abc/__init__.py | 4 ++-- src/modules_core/service/__init__.py | 4 ++-- 15 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/gismo/__init__.py b/src/gismo/__init__.py index a9e4465..e2d1c61 100644 --- a/src/gismo/__init__.py +++ b/src/gismo/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo/gismo.json b/src/gismo/gismo.json index d8f8c8d..48efbc3 100644 --- a/src/gismo/gismo.json +++ b/src/gismo/gismo.json @@ -3,7 +3,7 @@ "Name": "gismo", "Version": { "Major": "0", - "Minor": "2", + "Minor": "3", "Micro": "0" }, "Author": "Sven Heidemann", diff --git a/src/gismo_core/__init__.py b/src/gismo_core/__init__.py index f1838fc..98c9727 100644 --- a/src/gismo_core/__init__.py +++ b/src/gismo_core/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_core/abc/__init__.py b/src/gismo_core/abc/__init__.py index b41756e..2ef29e0 100644 --- a/src/gismo_core/abc/__init__.py +++ b/src/gismo_core/abc/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_core.abc' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_core/configuration/__init__.py b/src/gismo_core/configuration/__init__.py index affff5f..256c23c 100644 --- a/src/gismo_core/configuration/__init__.py +++ b/src/gismo_core/configuration/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_core.configuration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_core/service/__init__.py b/src/gismo_core/service/__init__.py index 97f2495..016bce9 100644 --- a/src/gismo_core/service/__init__.py +++ b/src/gismo_core/service/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_core.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_data/__init__.py b/src/gismo_data/__init__.py index 18b850e..f8cc746 100644 --- a/src/gismo_data/__init__.py +++ b/src/gismo_data/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_data' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_data/abc/__init__.py b/src/gismo_data/abc/__init__.py index 87b802e..1845f2d 100644 --- a/src/gismo_data/abc/__init__.py +++ b/src/gismo_data/abc/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_data.abc' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_data/migration/__init__.py b/src/gismo_data/migration/__init__.py index 49a2557..ff6ccc6 100644 --- a/src/gismo_data/migration/__init__.py +++ b/src/gismo_data/migration/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_data.migration' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_data/model/__init__.py b/src/gismo_data/model/__init__.py index f45fb29..7009a86 100644 --- a/src/gismo_data/model/__init__.py +++ b/src/gismo_data/model/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_data.model' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/gismo_data/service/__init__.py b/src/gismo_data/service/__init__.py index 67ad80d..76e0775 100644 --- a/src/gismo_data/service/__init__.py +++ b/src/gismo_data/service/__init__.py @@ -15,11 +15,11 @@ __title__ = 'gismo_data.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/modules/boot_log/__init__.py b/src/modules/boot_log/__init__.py index a6127ce..d6b52d8 100644 --- a/src/modules/boot_log/__init__.py +++ b/src/modules/boot_log/__init__.py @@ -15,11 +15,11 @@ __title__ = 'modules.boot_log' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports: VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/modules_core/__init__.py b/src/modules_core/__init__.py index 60a2666..88a2e59 100644 --- a/src/modules_core/__init__.py +++ b/src/modules_core/__init__.py @@ -15,11 +15,11 @@ __title__ = 'modules_core' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/modules_core/abc/__init__.py b/src/modules_core/abc/__init__.py index 235e917..4e57337 100644 --- a/src/modules_core/abc/__init__.py +++ b/src/modules_core/abc/__init__.py @@ -15,11 +15,11 @@ __title__ = 'modules_core.abc' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') diff --git a/src/modules_core/service/__init__.py b/src/modules_core/service/__init__.py index b5b68cb..bf3e373 100644 --- a/src/modules_core/service/__init__.py +++ b/src/modules_core/service/__init__.py @@ -15,11 +15,11 @@ __title__ = 'modules_core.service' __author__ = 'Sven Heidemann' __license__ = 'MIT' __copyright__ = 'Copyright (c) 2021 - 2022 sh-edraft.de' -__version__ = '0.2.0' +__version__ = '0.3.0' from collections import namedtuple # imports VersionInfo = namedtuple('VersionInfo', 'major minor micro') -version_info = VersionInfo(major='0', minor='2', micro='0') +version_info = VersionInfo(major='0', minor='3', micro='0') -- 2.45.2 From 2ae0a99783dd4b00c244e13a3e4d9699ba501d3c Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 19:11:36 +0100 Subject: [PATCH 38/48] build and improved config --- src/gismo/appsettings.json | 19 +++++++++++++++++-- src/gismo/gismo.json | 4 +++- src/modules/base/__init__.py | 24 ++++++++++++++++++++++++ src/modules/database/__init__.py | 24 ++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/gismo/appsettings.json b/src/gismo/appsettings.json index 629e6eb..cdfe149 100644 --- a/src/gismo/appsettings.json +++ b/src/gismo/appsettings.json @@ -5,11 +5,26 @@ "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": "" + } + ] } -} +} \ No newline at end of file diff --git a/src/gismo/gismo.json b/src/gismo/gismo.json index 48efbc3..81c9765 100644 --- a/src/gismo/gismo.json +++ b/src/gismo/gismo.json @@ -48,7 +48,9 @@ "../gismo_core/gismo-core.json", "../gismo_data/gismo-data.json", "../modules_core/modules-core.json", - "../modules/boot_log/boot-log.json" + "../modules/boot_log/boot-log.json", + "../modules/base/base.json", + "../modules/database/database.json" ] } } \ No newline at end of file diff --git a/src/modules/base/__init__.py b/src/modules/base/__init__.py index ad5eca3..307aa80 100644 --- a/src/modules/base/__init__.py +++ b/src/modules/base/__init__.py @@ -1 +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') diff --git a/src/modules/database/__init__.py b/src/modules/database/__init__.py index ad5eca3..3e9733f 100644 --- a/src/modules/database/__init__.py +++ b/src/modules/database/__init__.py @@ -1 +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') -- 2.45.2 From 42826a191424771e8197578d9eac7aa74d1ce7f7 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Wed, 8 Dec 2021 19:12:54 +0100 Subject: [PATCH 39/48] Improved config --- src/gismo/appsettings.example.json | 30 ++++++++++++++++++++++++++++++ src/gismo/appsettings.json | 16 ---------------- 2 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 src/gismo/appsettings.example.json diff --git a/src/gismo/appsettings.example.json b/src/gismo/appsettings.example.json new file mode 100644 index 0000000..cdfe149 --- /dev/null +++ b/src/gismo/appsettings.example.json @@ -0,0 +1,30 @@ +{ + "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": "" + } + ] + } +} \ No newline at end of file diff --git a/src/gismo/appsettings.json b/src/gismo/appsettings.json index cdfe149..a02074c 100644 --- a/src/gismo/appsettings.json +++ b/src/gismo/appsettings.json @@ -10,21 +10,5 @@ "Filename": "log_$start_time.log", "ConsoleLogLevel": "ERROR", "FileLogLevel": "WARN" - }, - "Discord": { - "Token": "" - }, - "Bot": { - "Prefix": "!g", - "Servers": [ - { - "Id": "", - "LoginMessageChannelId": "", - "LoginMessage": "", - "MessageDeleteTimer": 0, - "WelcomeMessage": "", - "GoodbyeMessage": "" - } - ] } } \ No newline at end of file -- 2.45.2 From fcc5b882b7291ddec39aacb32969785f9b5f0ec5 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Dec 2021 14:37:38 +0100 Subject: [PATCH 40/48] Added user joined voice channel model --- src/gismo_data/migration/migration_0_3_1.py | 35 ++++++ .../model/user_joined_voice_channel.py | 119 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/gismo_data/migration/migration_0_3_1.py create mode 100644 src/gismo_data/model/user_joined_voice_channel.py diff --git a/src/gismo_data/migration/migration_0_3_1.py b/src/gismo_data/migration/migration_0_3_1.py new file mode 100644 index 0000000..6102720 --- /dev/null +++ b/src/gismo_data/migration/migration_0_3_1.py @@ -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`;') + diff --git a/src/gismo_data/model/user_joined_voice_channel.py b/src/gismo_data/model/user_joined_voice_channel.py new file mode 100644 index 0000000..63604e0 --- /dev/null +++ b/src/gismo_data/model/user_joined_voice_channel.py @@ -0,0 +1,119 @@ +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`, `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 `UserJoinedVoiceChannel` ( + `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 `UserJoinedVoiceChannel` + 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 `UserJoinedVoiceChannel` + WHERE `Id` = {self._join_id}; + """) -- 2.45.2 From 39079b2b583bddd1800ee130b209592d31a73c2e Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Dec 2021 15:00:00 +0100 Subject: [PATCH 41/48] Added user joined voice channel repo --- src/gismo/startup.py | 3 + .../abc/user_joined_voice_channel_abc.py | 34 ++++++ .../user_joined_voice_channel_service.py | 107 ++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 src/gismo_data/abc/user_joined_voice_channel_abc.py create mode 100644 src/gismo_data/service/user_joined_voice_channel_service.py diff --git a/src/gismo/startup.py b/src/gismo/startup.py index 223262a..41800e4 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -18,6 +18,7 @@ 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 @@ -30,6 +31,7 @@ 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 @@ -79,6 +81,7 @@ class Startup(StartupABC): 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) diff --git a/src/gismo_data/abc/user_joined_voice_channel_abc.py b/src/gismo_data/abc/user_joined_voice_channel_abc.py new file mode 100644 index 0000000..57ad410 --- /dev/null +++ b/src/gismo_data/abc/user_joined_voice_channel_abc.py @@ -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 diff --git a/src/gismo_data/service/user_joined_voice_channel_service.py b/src/gismo_data/service/user_joined_voice_channel_service.py new file mode 100644 index 0000000..35f999d --- /dev/null +++ b/src/gismo_data/service/user_joined_voice_channel_service.py @@ -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) -- 2.45.2 From 3eaae4679fa7293009b3163749847843c364c819 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Dec 2021 15:39:46 +0100 Subject: [PATCH 42/48] Added logic to check table at startup --- src/gismo/appsettings.example.json | 5 +- src/gismo/startup.py | 2 + .../configuration/server_settings.py | 18 ++++++++ src/modules/database/database.py | 46 ++++++++++++++++++- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/gismo/appsettings.example.json b/src/gismo/appsettings.example.json index cdfe149..6a0c857 100644 --- a/src/gismo/appsettings.example.json +++ b/src/gismo/appsettings.example.json @@ -23,7 +23,10 @@ "LoginMessage": "", "MessageDeleteTimer": 0, "WelcomeMessage": "", - "GoodbyeMessage": "" + "GoodbyeMessage": "", + "MaxVoiceStateHours": 0, + "XpPerMessage": 0, + "XpPerOntimeHour": 0 } ] } diff --git a/src/gismo/startup.py b/src/gismo/startup.py index 41800e4..1d38c1d 100644 --- a/src/gismo/startup.py +++ b/src/gismo/startup.py @@ -23,6 +23,7 @@ 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 \ @@ -91,6 +92,7 @@ class Startup(StartupABC): # 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() diff --git a/src/gismo_core/configuration/server_settings.py b/src/gismo_core/configuration/server_settings.py index c298cb8..242217b 100644 --- a/src/gismo_core/configuration/server_settings.py +++ b/src/gismo_core/configuration/server_settings.py @@ -15,6 +15,9 @@ class ServerSettings(ConfigurationModelABC): self._login_message: str = '' self._welcome_message: 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 @property def id(self) -> str: @@ -40,6 +43,18 @@ class ServerSettings(ConfigurationModelABC): 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 + def from_dict(self, settings: dict): try: self._id = int(settings['Id']) @@ -48,6 +63,9 @@ class ServerSettings(ConfigurationModelABC): self._login_message = settings['LoginMessage'] self._welcome_message = settings['WelcomeMessage'] 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']) except Exception as e: Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings') Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/modules/database/database.py b/src/modules/database/database.py index a89c84d..752337a 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -7,10 +7,12 @@ 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 @@ -34,7 +36,8 @@ class Database(ModuleABC, OnReadyABC): user_repo: UserRepositoryABC, client_repo: ClientRepositoryABC, known_users: KnownUserRepositoryABC, - user_joins: UserJoinedServerRepositoryABC + user_joins: UserJoinedServerRepositoryABC, + user_joins_vc: UserJoinedVoiceChannelRepositoryABC ): self._config = config @@ -46,6 +49,7 @@ class Database(ModuleABC, OnReadyABC): 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 @@ -241,6 +245,45 @@ class Database(ModuleABC, OnReadyABC): 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() + + 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') @@ -249,6 +292,7 @@ class Database(ModuleABC, OnReadyABC): 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') -- 2.45.2 From 286c65325272ad486d41524ec863705c76bbc02f Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Dec 2021 17:24:16 +0100 Subject: [PATCH 43/48] Fixed bug in database module --- src/modules/database/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 752337a..414efd5 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -274,7 +274,7 @@ class Database(ModuleABC, OnReadyABC): 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: + 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) -- 2.45.2 From daa031bc571a676131b0b5533fcd3f70d4a08a0d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Dec 2021 18:12:09 +0100 Subject: [PATCH 44/48] Added logic to handle xp --- src/gismo/appsettings.example.json | 3 +- .../configuration/server_settings.py | 7 ++ src/gismo_data/model/user.py | 4 +- .../model/user_joined_voice_channel.py | 6 +- src/modules/base/base.py | 105 +++++++++++++++++- 5 files changed, 118 insertions(+), 7 deletions(-) diff --git a/src/gismo/appsettings.example.json b/src/gismo/appsettings.example.json index 6a0c857..c13db34 100644 --- a/src/gismo/appsettings.example.json +++ b/src/gismo/appsettings.example.json @@ -26,7 +26,8 @@ "GoodbyeMessage": "", "MaxVoiceStateHours": 0, "XpPerMessage": 0, - "XpPerOntimeHour": 0 + "XpPerOntimeHour": 0, + "AFKChannelIds": [] } ] } diff --git a/src/gismo_core/configuration/server_settings.py b/src/gismo_core/configuration/server_settings.py index 242217b..ae21cb0 100644 --- a/src/gismo_core/configuration/server_settings.py +++ b/src/gismo_core/configuration/server_settings.py @@ -18,6 +18,7 @@ class ServerSettings(ConfigurationModelABC): 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] = [] @property def id(self) -> str: @@ -55,6 +56,10 @@ class ServerSettings(ConfigurationModelABC): 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 + def from_dict(self, settings: dict): try: self._id = int(settings['Id']) @@ -66,6 +71,8 @@ class ServerSettings(ConfigurationModelABC): 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)) except Exception as e: Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings') Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') diff --git a/src/gismo_data/model/user.py b/src/gismo_data/model/user.py index 5597c07..83f4b9f 100644 --- a/src/gismo_data/model/user.py +++ b/src/gismo_data/model/user.py @@ -86,12 +86,12 @@ class User(TableABC): UPDATE `Users` SET `XP` = {self._xp}, `LastModifiedAt` = '{self._modified_at}' - WHERE `Id` = {self._user_id}; + WHERE `UserId` = {self._user_id}; """) @property def delete_string(self) -> str: return str(f""" DELETE FROM `Users` - WHERE `Id` = {self._user_id}; + WHERE `UserId` = {self._user_id}; """) diff --git a/src/gismo_data/model/user_joined_voice_channel.py b/src/gismo_data/model/user_joined_voice_channel.py index 63604e0..83729a3 100644 --- a/src/gismo_data/model/user_joined_voice_channel.py +++ b/src/gismo_data/model/user_joined_voice_channel.py @@ -81,9 +81,10 @@ class UserJoinedVoiceChannel(TableABC): if self._leaved_on is not None: return str(f""" INSERT INTO `UserJoinedVoiceChannel` ( - `UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` + `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( {self._user.user_id}, + {self._dc_channel_id}, '{self._joined_on}', '{self._leaved_on}', '{self._created_at}', @@ -93,9 +94,10 @@ class UserJoinedVoiceChannel(TableABC): else: return str(f""" INSERT INTO `UserJoinedVoiceChannel` ( - `UserId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` + `UserId`, `DiscordChannelId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` ) VALUES ( {self._user.user_id}, + {self._dc_channel_id}, '{self._joined_on}', '{self._created_at}', '{self._modified_at}' diff --git a/src/modules/base/base.py b/src/modules/base/base.py index 5d233ef..fc4d79f 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -14,10 +14,12 @@ 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 @@ -37,6 +39,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS known_users: KnownUserRepositoryABC, users: UserRepositoryABC, user_joins: UserJoinedServerRepositoryABC, + user_joins_vc: UserJoinedVoiceChannelRepositoryABC, bot: BotServiceABC, db: DatabaseContextABC, messenger: MessageServiceABC @@ -48,6 +51,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS 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 @@ -128,6 +132,70 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS 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 = (join.leaved_on - join.joined_on).total_seconds()/3600 + 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) @@ -143,7 +211,40 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS 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') - # todo: save ontime - # todo: add xp to user when he goes offline + 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) -- 2.45.2 From b436daeb357d3eed69aa46a3e0a5bc624956dcbd Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Dec 2021 18:43:00 +0100 Subject: [PATCH 45/48] Rounded ontime --- src/modules/base/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/base/base.py b/src/modules/base/base.py index fc4d79f..35c53eb 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -157,7 +157,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS join.leaved_on = datetime.now() # ontime as hours - ontime = (join.leaved_on - join.joined_on).total_seconds()/3600 + 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) -- 2.45.2 From 09a4ace8670ec0974b6cd581050cd9e16c27964d Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 21 Dec 2021 18:47:58 +0100 Subject: [PATCH 46/48] Fixed dazabase assignment bug --- src/gismo_data/model/user_joined_voice_channel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gismo_data/model/user_joined_voice_channel.py b/src/gismo_data/model/user_joined_voice_channel.py index 83729a3..8d29d04 100644 --- a/src/gismo_data/model/user_joined_voice_channel.py +++ b/src/gismo_data/model/user_joined_voice_channel.py @@ -110,12 +110,12 @@ class UserJoinedVoiceChannel(TableABC): UPDATE `UserJoinedVoiceChannel` SET `LeavedOn` = '{self._leaved_on}', `LastModifiedAt` = '{self._modified_at}' - WHERE `UserId` = {self._user.user_id}; + WHERE `JoinId` = {self._join_id}; """) @property def delete_string(self) -> str: return str(f""" DELETE FROM `UserJoinedVoiceChannel` - WHERE `Id` = {self._join_id}; + WHERE `JoinId` = {self._join_id}; """) -- 2.45.2 From 10ba5111582be769cf05045da105dd3f643a5528 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 27 Dec 2021 18:03:46 +0100 Subject: [PATCH 47/48] Added handling of members who are already online on startup --- src/modules/database/database.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/modules/database/database.py b/src/modules/database/database.py index 414efd5..65730df 100644 --- a/src/modules/database/database.py +++ b/src/modules/database/database.py @@ -19,6 +19,7 @@ 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 @@ -281,6 +282,25 @@ class Database(ModuleABC, OnReadyABC): # 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) -- 2.45.2 From dadaa6ac09854ab8b9678097d0eeaf23f60bf121 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Mon, 27 Dec 2021 18:14:59 +0100 Subject: [PATCH 48/48] Added logic to send team message when user joined --- src/gismo/appsettings.example.json | 4 +++- .../configuration/server_settings.py | 22 +++++++++++++++++++ src/modules/base/base.py | 12 ++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/gismo/appsettings.example.json b/src/gismo/appsettings.example.json index c13db34..7bd96f0 100644 --- a/src/gismo/appsettings.example.json +++ b/src/gismo/appsettings.example.json @@ -27,7 +27,9 @@ "MaxVoiceStateHours": 0, "XpPerMessage": 0, "XpPerOntimeHour": 0, - "AFKChannelIds": [] + "AFKChannelIds": [], + "AdminRoleIds": [], + "ModeratorRoleIds": [] } ] } diff --git a/src/gismo_core/configuration/server_settings.py b/src/gismo_core/configuration/server_settings.py index ae21cb0..d9e3402 100644 --- a/src/gismo_core/configuration/server_settings.py +++ b/src/gismo_core/configuration/server_settings.py @@ -14,11 +14,14 @@ class ServerSettings(ConfigurationModelABC): 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: @@ -40,6 +43,10 @@ class ServerSettings(ConfigurationModelABC): 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 @@ -60,6 +67,14 @@ class ServerSettings(ConfigurationModelABC): 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']) @@ -67,12 +82,19 @@ class ServerSettings(ConfigurationModelABC): 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()}') diff --git a/src/modules/base/base.py b/src/modules/base/base.py index 35c53eb..5fd7892 100644 --- a/src/modules/base/base.py +++ b/src/modules/base/base.py @@ -95,6 +95,18 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS 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) -- 2.45.2