1.0.0 #253
| @@ -11,6 +11,7 @@ from bot_data.migration.auto_role_migration import AutoRoleMigration | ||||
| from bot_data.migration.initial_migration import InitialMigration | ||||
| from bot_data.migration.level_migration import LevelMigration | ||||
| from bot_data.migration.stats_migration import StatsMigration | ||||
| from bot_data.migration.user_joined_game_server_migration import UserJoinedGameServerMigration | ||||
| from bot_data.migration.user_message_count_per_hour_migration import ( | ||||
|     UserMessageCountPerHourMigration, | ||||
| ) | ||||
| @@ -34,3 +35,4 @@ class StartupMigrationExtension(StartupExtensionABC): | ||||
|         services.add_transient(MigrationABC, AutoRoleFix1Migration)  # 30.12.2022 #151 - 0.3.0 | ||||
|         services.add_transient(MigrationABC, UserMessageCountPerHourMigration)  # 11.01.2023 #168 - 0.3.1 | ||||
|         services.add_transient(MigrationABC, ApiKeyMigration)  # 09.02.2023 #162 - 1.0.0 | ||||
|         services.add_transient(MigrationABC, UserJoinedGameServerMigration)  # 12.02.2023 #181 - 1.0.0 | ||||
|   | ||||
| @@ -200,6 +200,13 @@ | ||||
|         "error": { | ||||
|           "atr_not_found": "Das Attribut {} konnte nicht gefunden werden :(" | ||||
|         } | ||||
|       }, | ||||
|       "register": { | ||||
|         "success": "Spieler wurde mit dem Mitglied verlinkt :D", | ||||
|         "not_found": "Benutzer nicht gefunden!" | ||||
|       }, | ||||
|       "unregister": { | ||||
|         "success": "Verlinkung wurde entfernt :D" | ||||
|       } | ||||
|     }, | ||||
|     "boot_log": { | ||||
|   | ||||
| @@ -0,0 +1,52 @@ | ||||
| from abc import ABC, abstractmethod | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.model.user_joined_game_server import UserJoinedGameServer | ||||
|  | ||||
|  | ||||
| class UserJoinedGameServerRepositoryABC(ABC): | ||||
|     @abstractmethod | ||||
|     def __init__(self): | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_user_joined_game_servers(self) -> List[UserJoinedGameServer]: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_user_joined_game_server_by_id(self, id: int) -> UserJoinedGameServer: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_user_joined_game_servers_by_user_id(self, user_id: int) -> List[UserJoinedGameServer]: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_active_user_joined_game_server_by_user_id(self, user_id: int) -> UserJoinedGameServer: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def find_active_user_joined_game_server_by_user_id(self, user_id: int) -> Optional[UserJoinedGameServer]: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def find_active_user_joined_game_servers_by_user_id(self, user_id: int) -> List[Optional[UserJoinedGameServer]]: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def add_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def update_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def delete_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def delete_user_joined_game_server_by_user_id(self, user_id: int): | ||||
|         pass | ||||
| @@ -13,6 +13,7 @@ from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| from bot_data.abc.level_repository_abc import LevelRepositoryABC | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC | ||||
| from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC | ||||
| from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_joined_voice_channel_repository_abc import ( | ||||
|     UserJoinedVoiceChannelRepositoryABC, | ||||
| @@ -30,6 +31,7 @@ from bot_data.service.level_repository_service import LevelRepositoryService | ||||
| from bot_data.service.seeder_service import SeederService | ||||
| from bot_data.service.server_repository_service import ServerRepositoryService | ||||
| from bot_data.service.statistic_repository_service import StatisticRepositoryService | ||||
| from bot_data.service.user_joined_game_server_repository_service import UserJoinedGameServerRepositoryService | ||||
| from bot_data.service.user_joined_server_repository_service import ( | ||||
|     UserJoinedServerRepositoryService, | ||||
| ) | ||||
| @@ -58,6 +60,7 @@ class DataModule(ModuleABC): | ||||
|         services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService) | ||||
|         services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService) | ||||
|         services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService) | ||||
|         services.add_transient(UserJoinedGameServerRepositoryABC, UserJoinedGameServerRepositoryService) | ||||
|         services.add_transient(AutoRoleRepositoryABC, AutoRoleRepositoryService) | ||||
|         services.add_transient(LevelRepositoryABC, LevelRepositoryService) | ||||
|         services.add_transient(StatisticRepositoryABC, StatisticRepositoryService) | ||||
|   | ||||
| @@ -0,0 +1,52 @@ | ||||
| from bot_core.logging.database_logger import DatabaseLogger | ||||
| from bot_data.abc.migration_abc import MigrationABC | ||||
| from bot_data.db_context import DBContext | ||||
|  | ||||
|  | ||||
| class UserJoinedGameServerMigration(MigrationABC): | ||||
|     name = "1.0_UserJoinedGameServerMigration" | ||||
|  | ||||
|     def __init__(self, logger: DatabaseLogger, db: DBContext): | ||||
|         MigrationABC.__init__(self) | ||||
|         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 `UserJoinedGameServer` ( | ||||
|                 `Id` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                 `UserId` BIGINT NOT NULL, | ||||
|                 `GameServer` VARCHAR(255) NOT NULL, | ||||
|                 `JoinedOn` DATETIME(6) NOT NULL, | ||||
|                 `LeavedOn` DATETIME(6), | ||||
|                 `CreatedAt` DATETIME(6), | ||||
|                 `LastModifiedAt` DATETIME(6), | ||||
|                 FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`), | ||||
|                 PRIMARY KEY(`Id`) | ||||
|             ); | ||||
|             """ | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str( | ||||
|                 f""" | ||||
|             ALTER TABLE Users ADD MinecraftId VARCHAR(255) NULL AFTER XP; | ||||
|             """ | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|     def downgrade(self): | ||||
|         self._cursor.execute("DROP TABLE `UserJoinedGameServer`;") | ||||
|         self._cursor.execute( | ||||
|             str( | ||||
|                 f""" | ||||
|             ALTER TABLE Users DROP COLUMN MinecraftId; | ||||
|             """ | ||||
|             ) | ||||
|         ) | ||||
| @@ -11,6 +11,7 @@ class User(TableABC): | ||||
|         self, | ||||
|         dc_id: int, | ||||
|         xp: int, | ||||
|         minecraft_id: Optional[str], | ||||
|         server: Optional[Server], | ||||
|         created_at: datetime = None, | ||||
|         modified_at: datetime = None, | ||||
| @@ -19,6 +20,7 @@ class User(TableABC): | ||||
|         self._user_id = id | ||||
|         self._discord_id = dc_id | ||||
|         self._xp = xp | ||||
|         self._minecraft_id = minecraft_id | ||||
|         self._server = server | ||||
|  | ||||
|         TableABC.__init__(self) | ||||
| @@ -42,6 +44,14 @@ class User(TableABC): | ||||
|         self._modified_at = datetime.now().isoformat() | ||||
|         self._xp = value | ||||
|  | ||||
|     @property | ||||
|     def minecraft_id(self) -> Optional[str]: | ||||
|         return self._minecraft_id | ||||
|  | ||||
|     @minecraft_id.setter | ||||
|     def minecraft_id(self, value: str): | ||||
|         self._minecraft_id = value | ||||
|  | ||||
|     @property | ||||
|     def server(self) -> Optional[Server]: | ||||
|         return self._server | ||||
| @@ -96,10 +106,11 @@ class User(TableABC): | ||||
|         return str( | ||||
|             f""" | ||||
|             INSERT INTO `Users` ( | ||||
|                 `DiscordId`, `XP`, `ServerId`, `CreatedAt`, `LastModifiedAt` | ||||
|                 `DiscordId`, `XP`, `MinecraftId`, `ServerId`, `CreatedAt`, `LastModifiedAt` | ||||
|             ) VALUES ( | ||||
|                 {self._discord_id}, | ||||
|                 {self._xp}, | ||||
|                 '{"NULL" if self._minecraft_id is None else self._minecraft_id}', | ||||
|                 {self._server.server_id}, | ||||
|                 '{self._created_at}', | ||||
|                 '{self._modified_at}' | ||||
| @@ -113,6 +124,7 @@ class User(TableABC): | ||||
|             f""" | ||||
|             UPDATE `Users` | ||||
|             SET `XP` = {self._xp}, | ||||
|             `MinecraftId` = '{"NULL" if self._minecraft_id is None else self._minecraft_id}', | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `UserId` = {self._user_id}; | ||||
|         """ | ||||
|   | ||||
							
								
								
									
										154
									
								
								kdb-bot/src/bot_data/model/user_joined_game_server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								kdb-bot/src/bot_data/model/user_joined_game_server.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,154 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| from cpl_core.database import TableABC | ||||
|  | ||||
| from bot_data.model.user import User | ||||
|  | ||||
|  | ||||
| class UserJoinedGameServer(TableABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         user: User, | ||||
|         game_server: str, | ||||
|         joined_on: datetime, | ||||
|         leaved_on: datetime = None, | ||||
|         created_at: datetime = None, | ||||
|         modified_at: datetime = None, | ||||
|         id=0, | ||||
|     ): | ||||
|         self._id = id | ||||
|         self._user = user | ||||
|         self._game_server = game_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 id(self) -> int: | ||||
|         return self._id | ||||
|  | ||||
|     @property | ||||
|     def user(self) -> User: | ||||
|         return self._user | ||||
|  | ||||
|     @property | ||||
|     def game_server(self) -> str: | ||||
|         return self._game_server | ||||
|  | ||||
|     @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 `UserJoinedGameServer`; | ||||
|         """ | ||||
|         ) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_id_string(id: int) -> str: | ||||
|         return str( | ||||
|             f""" | ||||
|             SELECT * FROM `UserJoinedGameServer` | ||||
|             WHERE `Id` = {id}; | ||||
|         """ | ||||
|         ) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_user_id_string(id: int) -> str: | ||||
|         return str( | ||||
|             f""" | ||||
|             SELECT * FROM `UserJoinedGameServer` | ||||
|             WHERE `UserId` = {id}; | ||||
|         """ | ||||
|         ) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_active_by_user_id_string(id: int) -> str: | ||||
|         return str( | ||||
|             f""" | ||||
|             SELECT * FROM `UserJoinedGameServer` | ||||
|             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 `UserJoinedGameServer` ( | ||||
|                     `UserId`, `GameServer`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` | ||||
|                 ) VALUES ( | ||||
|                     {self._user.user_id}, | ||||
|                     '{self._game_server}', | ||||
|                     '{self._joined_on}', | ||||
|                     '{self._leaved_on}', | ||||
|                     '{self._created_at}', | ||||
|                     '{self._modified_at}' | ||||
|                 ); | ||||
|             """ | ||||
|             ) | ||||
|         else: | ||||
|             return str( | ||||
|                 f""" | ||||
|                 INSERT INTO `UserJoinedGameServer` ( | ||||
|                     `UserId`, `GameServer`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` | ||||
|                 ) VALUES ( | ||||
|                     {self._user.user_id}, | ||||
|                     '{self._game_server}', | ||||
|                     '{self._joined_on}', | ||||
|                     '{self._created_at}', | ||||
|                     '{self._modified_at}' | ||||
|                 ); | ||||
|             """ | ||||
|             ) | ||||
|  | ||||
|     @property | ||||
|     def udpate_string(self) -> str: | ||||
|         return str( | ||||
|             f""" | ||||
|             UPDATE `UserJoinedGameServer` | ||||
|             SET `LeavedOn` = '{self._leaved_on}', | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `Id` = {self._id}; | ||||
|         """ | ||||
|         ) | ||||
|  | ||||
|     @property | ||||
|     def delete_string(self) -> str: | ||||
|         return str( | ||||
|             f""" | ||||
|             DELETE FROM `UserJoinedGameServer` | ||||
|             WHERE `Id` = {self._id}; | ||||
|         """ | ||||
|         ) | ||||
|  | ||||
|     @staticmethod | ||||
|     def delete_by_user_id_string(id: int) -> str: | ||||
|         return str( | ||||
|             f""" | ||||
|             DELETE FROM `UserJoinedGameServer` | ||||
|             WHERE `UserId` = {id} | ||||
|     """ | ||||
|         ) | ||||
| @@ -2,7 +2,6 @@ from enum import Enum | ||||
|  | ||||
|  | ||||
| class UserRoleEnum(Enum): | ||||
|  | ||||
|     member = 0 | ||||
|     moderator = 1 | ||||
|     admin = 2 | ||||
|   | ||||
| @@ -0,0 +1,160 @@ | ||||
| from typing import Optional | ||||
|  | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_core.logging.database_logger import DatabaseLogger | ||||
| from bot_data.abc.user_joined_game_server_repository_abc import ( | ||||
|     UserJoinedGameServerRepositoryABC, | ||||
| ) | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.model.user_joined_game_server import UserJoinedGameServer | ||||
|  | ||||
|  | ||||
| class UserJoinedGameServerRepositoryService(UserJoinedGameServerRepositoryABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         logger: DatabaseLogger, | ||||
|         db_context: DatabaseContextABC, | ||||
|         users: UserRepositoryABC, | ||||
|     ): | ||||
|         self._logger = logger | ||||
|         self._context = db_context | ||||
|  | ||||
|         self._users = users | ||||
|  | ||||
|         UserJoinedGameServerRepositoryABC.__init__(self) | ||||
|  | ||||
|     def get_user_joined_game_servers(self) -> List[UserJoinedGameServer]: | ||||
|         joins = List(UserJoinedGameServer) | ||||
|         self._logger.trace( | ||||
|             __name__, | ||||
|             f"Send SQL command: {UserJoinedGameServer.get_select_all_string()}", | ||||
|         ) | ||||
|         results = self._context.select(UserJoinedGameServer.get_select_all_string()) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}") | ||||
|             joins.append( | ||||
|                 UserJoinedGameServer( | ||||
|                     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_game_server_by_id(self, id: int) -> UserJoinedGameServer: | ||||
|         self._logger.trace( | ||||
|             __name__, | ||||
|             f"Send SQL command: {UserJoinedGameServer.get_select_by_id_string(id)}", | ||||
|         ) | ||||
|         result = self._context.select(UserJoinedGameServer.get_select_by_id_string(id))[0] | ||||
|         return UserJoinedGameServer( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
|     def get_user_joined_game_servers_by_user_id(self, user_id: int) -> List[UserJoinedGameServer]: | ||||
|         joins = List(UserJoinedGameServer) | ||||
|         self._logger.trace( | ||||
|             __name__, | ||||
|             f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}", | ||||
|         ) | ||||
|         results = self._context.select(UserJoinedGameServer.get_select_by_user_id_string(user_id)) | ||||
|         for result in results: | ||||
|             joins.append( | ||||
|                 UserJoinedGameServer( | ||||
|                     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_game_server_by_user_id(self, user_id: int) -> UserJoinedGameServer: | ||||
|         self._logger.trace( | ||||
|             __name__, | ||||
|             f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}", | ||||
|         ) | ||||
|         result = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id))[0] | ||||
|         return UserJoinedGameServer( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
|     def find_active_user_joined_game_server_by_user_id(self, user_id: int) -> Optional[UserJoinedGameServer]: | ||||
|         self._logger.trace( | ||||
|             __name__, | ||||
|             f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}", | ||||
|         ) | ||||
|         result = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id)) | ||||
|         if result is None or len(result) == 0: | ||||
|             return None | ||||
|  | ||||
|         result = result[0] | ||||
|  | ||||
|         return UserJoinedGameServer( | ||||
|             self._users.get_user_by_id(result[1]), | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             result[5], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
|     def find_active_user_joined_game_servers_by_user_id(self, user_id: int) -> List[Optional[UserJoinedGameServer]]: | ||||
|         self._logger.trace( | ||||
|             __name__, | ||||
|             f"Send SQL command: {UserJoinedGameServer.get_select_active_by_user_id_string(user_id)}", | ||||
|         ) | ||||
|         result = List(UserJoinedGameServer) | ||||
|         db_results = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id)) | ||||
|  | ||||
|         for db_result in db_results: | ||||
|             result.append( | ||||
|                 UserJoinedGameServer( | ||||
|                     self._users.get_user_by_id(db_result[1]), | ||||
|                     db_result[2], | ||||
|                     db_result[3], | ||||
|                     db_result[4], | ||||
|                     db_result[5], | ||||
|                     id=db_result[0], | ||||
|                 ) | ||||
|             ) | ||||
|  | ||||
|         return result | ||||
|  | ||||
|     def add_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): | ||||
|         self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.insert_string}") | ||||
|         self._context.cursor.execute(user_joined_game_server.insert_string) | ||||
|  | ||||
|     def update_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): | ||||
|         self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.udpate_string}") | ||||
|         self._context.cursor.execute(user_joined_game_server.udpate_string) | ||||
|  | ||||
|     def delete_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): | ||||
|         self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.delete_string}") | ||||
|         self._context.cursor.execute(user_joined_game_server.delete_string) | ||||
|  | ||||
|     def delete_user_joined_game_server_by_user_id(self, user_id: int): | ||||
|         self._logger.trace( | ||||
|             __name__, | ||||
|             f"Send SQL command: {UserJoinedGameServer.delete_by_user_id_string}", | ||||
|         ) | ||||
|         self._context.cursor.execute(UserJoinedGameServer.delete_by_user_id_string(user_id)) | ||||
| @@ -33,7 +33,10 @@ class UserRepositoryService(UserRepositoryABC): | ||||
|                 User( | ||||
|                     result[1], | ||||
|                     result[2], | ||||
|                     self._servers.get_server_by_id(result[3]), | ||||
|                     result[3], | ||||
|                     self._servers.get_server_by_id(result[4]), | ||||
|                     result[5], | ||||
|                     result[6], | ||||
|                     id=result[0], | ||||
|                 ) | ||||
|             ) | ||||
| @@ -47,7 +50,10 @@ class UserRepositoryService(UserRepositoryABC): | ||||
|         return User( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             self._servers.get_server_by_id(result[3]), | ||||
|             result[3], | ||||
|             self._servers.get_server_by_id(result[4]), | ||||
|             result[5], | ||||
|             result[6], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
| @@ -62,7 +68,10 @@ class UserRepositoryService(UserRepositoryABC): | ||||
|         return User( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             self._servers.get_server_by_id(result[3]), | ||||
|             result[3], | ||||
|             self._servers.get_server_by_id(result[4]), | ||||
|             result[5], | ||||
|             result[6], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
| @@ -78,7 +87,10 @@ class UserRepositoryService(UserRepositoryABC): | ||||
|                 User( | ||||
|                     result[1], | ||||
|                     result[2], | ||||
|                     self._servers.get_server_by_id(result[3]), | ||||
|                     result[3], | ||||
|                     self._servers.get_server_by_id(result[4]), | ||||
|                     result[5], | ||||
|                     result[6], | ||||
|                     id=result[0], | ||||
|                 ) | ||||
|             ) | ||||
| @@ -97,7 +109,10 @@ class UserRepositoryService(UserRepositoryABC): | ||||
|                 User( | ||||
|                     result[1], | ||||
|                     result[2], | ||||
|                     self._servers.get_server_by_id(result[3]), | ||||
|                     result[3], | ||||
|                     self._servers.get_server_by_id(result[4]), | ||||
|                     result[5], | ||||
|                     result[6], | ||||
|                     id=result[0], | ||||
|                 ) | ||||
|             ) | ||||
| @@ -114,7 +129,10 @@ class UserRepositoryService(UserRepositoryABC): | ||||
|         return User( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             self._servers.get_server_by_id(result[3]), | ||||
|             result[3], | ||||
|             self._servers.get_server_by_id(result[4]), | ||||
|             result[5], | ||||
|             result[6], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
| @@ -132,9 +150,10 @@ class UserRepositoryService(UserRepositoryABC): | ||||
|         return User( | ||||
|             result[1], | ||||
|             result[2], | ||||
|             self._servers.get_server_by_id(result[3]), | ||||
|             result[4], | ||||
|             result[3], | ||||
|             self._servers.get_server_by_id(result[4]), | ||||
|             result[5], | ||||
|             result[6], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
|   | ||||
| @@ -17,6 +17,7 @@ from bot_data.model.known_user import KnownUser | ||||
| from bot_data.model.level import Level | ||||
| from bot_data.model.server import Server | ||||
| from bot_data.model.user import User | ||||
| from bot_data.model.user_joined_game_server import UserJoinedGameServer | ||||
| from bot_data.model.user_joined_server import UserJoinedServer | ||||
| from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel | ||||
| from bot_data.model.user_role_enum import UserRoleEnum | ||||
| @@ -49,7 +50,7 @@ class QueryABC(ObjectType): | ||||
|                 sort.from_dict(kwargs["sort"]) | ||||
|                 kwargs["sort"] = sort | ||||
|  | ||||
|             collection = get_collection(*args) | ||||
|             collection: List = get_collection(*args) | ||||
|             user = Route.get_user() | ||||
|  | ||||
|             if user == "system" or user.auth_role == AuthRoleEnum.admin: | ||||
| @@ -141,6 +142,13 @@ class QueryABC(ObjectType): | ||||
|                     access = True | ||||
|                     break | ||||
|  | ||||
|         elif type(element) == UserJoinedGameServer: | ||||
|             for u in user.users: | ||||
|                 u: User = u | ||||
|                 if u.user_id == element.user.user_id: | ||||
|                     access = True | ||||
|                     break | ||||
|  | ||||
|         return access | ||||
|  | ||||
|     @ServiceProviderABC.inject | ||||
|   | ||||
| @@ -30,8 +30,10 @@ class UserFilter(FilterABC): | ||||
|         self._discord_id = None | ||||
|         self._name = None | ||||
|         self._xp = None | ||||
|         self._minecraft_id = None | ||||
|         self._ontime = None | ||||
|         self._level: Optional[LevelFilter] = None | ||||
|         self._server = None | ||||
|  | ||||
|     def from_dict(self, values: dict): | ||||
|         if "id" in values: | ||||
| @@ -46,6 +48,9 @@ class UserFilter(FilterABC): | ||||
|         if "xp" in values: | ||||
|             self._xp = int(values["xp"]) | ||||
|  | ||||
|         if "minecraftId" in values: | ||||
|             self._minecraft_id = values["minecraftId"] | ||||
|  | ||||
|         if "ontime" in values: | ||||
|             self._ontime = int(values["ontime"]) | ||||
|  | ||||
| @@ -61,7 +66,7 @@ class UserFilter(FilterABC): | ||||
|  | ||||
|     def filter(self, query: List[User]) -> List[User]: | ||||
|         if self._id is not None: | ||||
|             query = query.where(lambda x: x.id == self._id) | ||||
|             query = query.where(lambda x: x.user_id == self._id) | ||||
|  | ||||
|         if self._discord_id is not None: | ||||
|             query = query.where(lambda x: x.discord_id == self._discord_id) | ||||
| @@ -75,6 +80,9 @@ class UserFilter(FilterABC): | ||||
|         if self._xp is not None: | ||||
|             query = query.where(lambda x: x.xp == self._xp) | ||||
|  | ||||
|         if self._minecraft_id is not None: | ||||
|             query = query.where(lambda x: x.minecraft_id == self._minecraft_id) | ||||
|  | ||||
|         if self._ontime is not None: | ||||
|             query = query.where(lambda x: self._client_utils.get_ontime_for_user(x) == self._ontime) | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,48 @@ | ||||
| from cpl_core.dependency_injection import ServiceProviderABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_query.extension import List | ||||
|  | ||||
| from bot_data.model.user_joined_game_server import UserJoinedGameServer | ||||
| from bot_graphql.abc.filter_abc import FilterABC | ||||
|  | ||||
|  | ||||
| class UserJoinedGameServerFilter(FilterABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         services: ServiceProviderABC, | ||||
|         bot: DiscordBotServiceABC, | ||||
|     ): | ||||
|         FilterABC.__init__(self) | ||||
|  | ||||
|         self._services = services | ||||
|         self._bot = bot | ||||
|  | ||||
|         self._id = None | ||||
|         self._game_server = None | ||||
|         self._user = None | ||||
|  | ||||
|     def from_dict(self, values: dict): | ||||
|         if "id" in values: | ||||
|             self._id = int(values["id"]) | ||||
|  | ||||
|         if "gameServer" in values: | ||||
|             self._game_server = values["gameServer"] | ||||
|  | ||||
|         if "user" in values: | ||||
|             from bot_graphql.filter.user_filter import UserFilter | ||||
|  | ||||
|             self._user: UserFilter = self._services.get_service(UserFilter) | ||||
|             self._user.from_dict(values["user"]) | ||||
|  | ||||
|     def filter(self, query: List[UserJoinedGameServer]) -> List[UserJoinedGameServer]: | ||||
|         if self._id is not None: | ||||
|             query = query.where(lambda x: x.id == self._id) | ||||
|  | ||||
|         if self._game_server is not None: | ||||
|             query = query.where(lambda x: x.game_server == self._game_server) | ||||
|  | ||||
|         if self._user is not None: | ||||
|             users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.user_id) | ||||
|             query = query.where(lambda x: x.user.user_id in users) | ||||
|  | ||||
|         return query | ||||
| @@ -14,6 +14,7 @@ from bot_graphql.filter.client_filter import ClientFilter | ||||
| from bot_graphql.filter.level_filter import LevelFilter | ||||
| from bot_graphql.filter.server_filter import ServerFilter | ||||
| from bot_graphql.filter.user_filter import UserFilter | ||||
| from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter | ||||
| from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter | ||||
| from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter | ||||
| from bot_graphql.graphql_service import GraphQLService | ||||
| @@ -21,6 +22,7 @@ from bot_graphql.mutation import Mutation | ||||
| from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation | ||||
| from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation | ||||
| from bot_graphql.mutations.level_mutation import LevelMutation | ||||
| from bot_graphql.mutations.user_joined_game_server_mutation import UserJoinedGameServerMutation | ||||
| from bot_graphql.mutations.user_mutation import UserMutation | ||||
| from bot_graphql.queries.auto_role_query import AutoRoleQuery | ||||
| from bot_graphql.queries.auto_role_rule_query import AutoRoleRuleQuery | ||||
| @@ -28,6 +30,7 @@ from bot_graphql.queries.client_query import ClientQuery | ||||
| from bot_graphql.queries.known_user_query import KnownUserQuery | ||||
| from bot_graphql.queries.level_query import LevelQuery | ||||
| from bot_graphql.queries.server_query import ServerQuery | ||||
| from bot_graphql.queries.user_joined_game_server_query import UserJoinedGameServerQuery | ||||
| from bot_graphql.queries.user_joined_server_query import UserJoinedServerQuery | ||||
| from bot_graphql.queries.user_joined_voice_channel_query import UserJoinedVoiceChannelQuery | ||||
| from bot_graphql.queries.user_query import UserQuery | ||||
| @@ -58,21 +61,24 @@ class GraphQLModule(ModuleABC): | ||||
|         services.add_transient(QueryABC, UserQuery) | ||||
|         services.add_transient(QueryABC, UserJoinedServerQuery) | ||||
|         services.add_transient(QueryABC, UserJoinedVoiceChannelQuery) | ||||
|         services.add_transient(QueryABC, UserJoinedGameServerQuery) | ||||
|  | ||||
|         # filters | ||||
|         services.add_singleton(FilterABC, AutoRoleFilter) | ||||
|         services.add_singleton(FilterABC, AutoRoleRuleFilter) | ||||
|         services.add_singleton(FilterABC, ClientFilter) | ||||
|         services.add_singleton(FilterABC, LevelFilter) | ||||
|         services.add_singleton(FilterABC, ServerFilter) | ||||
|         services.add_singleton(FilterABC, UserFilter) | ||||
|         services.add_singleton(FilterABC, UserJoinedServerFilter) | ||||
|         services.add_singleton(FilterABC, UserJoinedVoiceChannelFilter) | ||||
|         services.add_transient(FilterABC, AutoRoleFilter) | ||||
|         services.add_transient(FilterABC, AutoRoleRuleFilter) | ||||
|         services.add_transient(FilterABC, ClientFilter) | ||||
|         services.add_transient(FilterABC, LevelFilter) | ||||
|         services.add_transient(FilterABC, ServerFilter) | ||||
|         services.add_transient(FilterABC, UserFilter) | ||||
|         services.add_transient(FilterABC, UserJoinedServerFilter) | ||||
|         services.add_transient(FilterABC, UserJoinedVoiceChannelFilter) | ||||
|         services.add_transient(FilterABC, UserJoinedGameServerFilter) | ||||
|  | ||||
|         # mutations | ||||
|         services.add_transient(QueryABC, AutoRoleMutation) | ||||
|         services.add_transient(QueryABC, AutoRoleRuleMutation) | ||||
|         services.add_transient(QueryABC, LevelMutation) | ||||
|         services.add_transient(QueryABC, UserMutation) | ||||
|         services.add_transient(QueryABC, UserJoinedGameServerMutation) | ||||
|  | ||||
|         services.add_transient(SeederService) | ||||
|   | ||||
| @@ -3,4 +3,5 @@ type Mutation { | ||||
|     autoRoleRule: AutoRoleRuleMutation | ||||
|     level: LevelMutation | ||||
|     user: UserMutation | ||||
|     userJoinedGameServer: UserJoinedGameServerMutation | ||||
| } | ||||
| @@ -18,10 +18,13 @@ type Query { | ||||
|     servers(filter: ServerFilter, page: Page, sort: Sort): [Server] | ||||
|  | ||||
|     userJoinedServerCount: Int | ||||
|     userJoinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [User] | ||||
|     userJoinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer] | ||||
|  | ||||
|     userJoinedVoiceChannelCount: Int | ||||
|     userJoinedVoiceChannels(filter: UserJoinedVoiceChannelFilter, page: Page, sort: Sort): [User] | ||||
|     userJoinedVoiceChannels(filter: UserJoinedVoiceChannelFilter, page: Page, sort: Sort): [UserJoinedVoiceChannel] | ||||
|  | ||||
|     userJoinedGameServerCount: Int | ||||
|     userJoinedGameServers(filter: UserJoinedGameServerFilter, page: Page, sort: Sort): [UserJoinedGameServer] | ||||
|  | ||||
|     userCount: Int | ||||
|     users(filter: UserFilter, page: Page, sort: Sort): [User] | ||||
|   | ||||
| @@ -3,6 +3,7 @@ type User implements TableQuery { | ||||
|     discordId: String | ||||
|     name: String | ||||
|     xp: Int | ||||
|     minecraftId: String | ||||
|     ontime: Float | ||||
|     level: Level | ||||
|  | ||||
| @@ -12,6 +13,9 @@ type User implements TableQuery { | ||||
|     joinedVoiceChannels(filter: UserJoinedVoiceChannelFilter, page: Page, sort: Sort): [UserJoinedVoiceChannel] | ||||
|     joinedVoiceChannelCount: Int | ||||
|  | ||||
|     userJoinedGameServerCount: Int | ||||
|     userJoinedGameServers(filter: UserJoinedGameServerFilter, page: Page, sort: Sort): [UserJoinedGameServer] | ||||
|  | ||||
|     server: Server | ||||
|  | ||||
|     createdAt: String | ||||
| @@ -23,6 +27,7 @@ input UserFilter { | ||||
|     discordId: String | ||||
|     name: String | ||||
|     xp: Int | ||||
|     minecraftId: String | ||||
|     ontime: Float | ||||
|     level: LevelFilter | ||||
|     server: ServerFilter | ||||
|   | ||||
							
								
								
									
										28
									
								
								kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| type UserJoinedGameServer implements TableQuery { | ||||
|     id: ID | ||||
|     gameServer: String | ||||
|     user: User | ||||
|     joinedOn: String | ||||
|     leavedOn: String | ||||
|  | ||||
|     createdAt: String | ||||
|     modifiedAt: String | ||||
| } | ||||
|  | ||||
| input UserJoinedGameServerFilter { | ||||
|     id: ID | ||||
|     gameServer: String | ||||
|     user: UserFilter | ||||
|     joinedOn: String | ||||
|     leavedOn: String | ||||
| } | ||||
|  | ||||
| type UserJoinedGameServerMutation { | ||||
|     userJoined(input: UserJoinedGameServerInput!): UserJoinedGameServer | ||||
|     userLeaved(input: UserJoinedGameServerInput!): UserJoinedGameServer | ||||
| } | ||||
|  | ||||
| input UserJoinedGameServerInput { | ||||
|     gameServer: String! | ||||
|     userId: ID! | ||||
| } | ||||
| @@ -1,8 +1,10 @@ | ||||
| from ariadne import MutationType | ||||
|  | ||||
| from bot_data.model.user_joined_game_server import UserJoinedGameServer | ||||
| from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation | ||||
| from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation | ||||
| from bot_graphql.mutations.level_mutation import LevelMutation | ||||
| from bot_graphql.mutations.user_joined_game_server_mutation import UserJoinedGameServerMutation | ||||
| from bot_graphql.mutations.user_mutation import UserMutation | ||||
|  | ||||
|  | ||||
| @@ -13,27 +15,12 @@ class Mutation(MutationType): | ||||
|         auto_role_rule_mutation: AutoRoleRuleMutation, | ||||
|         level_mutation: LevelMutation, | ||||
|         user_mutation: UserMutation, | ||||
|         user_joined_game_server: UserJoinedGameServerMutation, | ||||
|     ): | ||||
|         MutationType.__init__(self) | ||||
|  | ||||
|         self._auto_role_mutation = auto_role_mutation | ||||
|         self._auto_role_rule_mutation = auto_role_rule_mutation | ||||
|         self._level_mutation = level_mutation | ||||
|         self._user_mutation = user_mutation | ||||
|  | ||||
|         self.set_field("autoRole", self.resolve_auto_role) | ||||
|         self.set_field("autoRoleRule", self.resolve_auto_role_rule) | ||||
|         self.set_field("level", self.resolve_level) | ||||
|         self.set_field("user", self.resolve_user) | ||||
|  | ||||
|     def resolve_auto_role(self, *_): | ||||
|         return self._auto_role_mutation | ||||
|  | ||||
|     def resolve_auto_role_rule(self, *_): | ||||
|         return self._auto_role_rule_mutation | ||||
|  | ||||
|     def resolve_level(self, *_): | ||||
|         return self._level_mutation | ||||
|  | ||||
|     def resolve_user(self, *_): | ||||
|         return self._user_mutation | ||||
|         self.set_field("autoRole", lambda *_: auto_role_mutation) | ||||
|         self.set_field("autoRoleRule", lambda *_: auto_role_rule_mutation) | ||||
|         self.set_field("level", lambda *_: level_mutation) | ||||
|         self.set_field("user", lambda *_: user_mutation) | ||||
|         self.set_field("userJoinedGameServer", lambda *_: user_joined_game_server) | ||||
|   | ||||
| @@ -0,0 +1,84 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_core.logging import LoggerABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
|  | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| from bot_data.model.user_joined_game_server import UserJoinedGameServer | ||||
| from bot_data.model.user_role_enum import UserRoleEnum | ||||
| from bot_graphql.abc.query_abc import QueryABC | ||||
| from modules.base.abc.base_helper_abc import BaseHelperABC | ||||
| from modules.base.configuration.base_server_settings import BaseServerSettings | ||||
| from modules.permission.service.permission_service import PermissionService | ||||
|  | ||||
|  | ||||
| class UserJoinedGameServerMutation(QueryABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         logger: LoggerABC, | ||||
|         base_helper: BaseHelperABC, | ||||
|         servers: ServerRepositoryABC, | ||||
|         users: UserRepositoryABC, | ||||
|         user_joined_game_servers: UserJoinedGameServerRepositoryABC, | ||||
|         bot: DiscordBotServiceABC, | ||||
|         db: DatabaseContextABC, | ||||
|         permissions: PermissionService, | ||||
|     ): | ||||
|         QueryABC.__init__(self, "UserJoinedGameServerMutation") | ||||
|  | ||||
|         self._logger = logger | ||||
|         self._base_helper = base_helper | ||||
|         self._servers = servers | ||||
|         self._users = users | ||||
|         self._user_joined_game_servers = user_joined_game_servers | ||||
|         self._bot = bot | ||||
|         self._db = db | ||||
|         self._permissions = permissions | ||||
|  | ||||
|         self.set_field("userJoined", self.resolve_user_joined) | ||||
|         self.set_field("userLeaved", self.resolve_user_leaved) | ||||
|  | ||||
|     def resolve_user_joined(self, *_, input: dict): | ||||
|         user = self._users.get_user_by_id(input["userId"]) | ||||
|         self._can_user_mutate_data(user.server, UserRoleEnum.admin) | ||||
|  | ||||
|         active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.user_id) | ||||
|         if active is not None: | ||||
|             self._logger.debug( | ||||
|                 __name__, | ||||
|                 f"Skip UserJoinedGameServer for user {user.user_id}. User already plays on {active.game_server}.", | ||||
|             ) | ||||
|             return | ||||
|  | ||||
|         new = UserJoinedGameServer(user, input["gameServer"], datetime.now()) | ||||
|         self._user_joined_game_servers.add_user_joined_game_server(new) | ||||
|         self._db.save_changes() | ||||
|  | ||||
|         return self._user_joined_game_servers.get_active_user_joined_game_server_by_user_id(user.user_id) | ||||
|  | ||||
|     def resolve_user_leaved(self, *_, input: dict): | ||||
|         user = self._users.get_user_by_id(input["userId"]) | ||||
|         self._can_user_mutate_data(user.server, UserRoleEnum.admin) | ||||
|  | ||||
|         active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.user_id) | ||||
|         if active is None: | ||||
|             return None | ||||
|         active.leaved_on = datetime.now() | ||||
|  | ||||
|         settings: BaseServerSettings = self._base_helper.get_config(user.server.discord_server_id) | ||||
|  | ||||
|         ontime = round((active.leaved_on - active.joined_on).total_seconds() / 3600, 2) | ||||
|         old_xp = user.xp | ||||
|         user.xp += round(ontime * settings.xp_per_ontime_hour) | ||||
|  | ||||
|         self._user_joined_game_servers.update_user_joined_game_server(active) | ||||
|         self._db.save_changes() | ||||
|         self._logger.debug( | ||||
|             __name__, | ||||
|             f"User {user} leaved_on {active.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}", | ||||
|         ) | ||||
|  | ||||
|         return active | ||||
| @@ -0,0 +1,37 @@ | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
|  | ||||
| from bot_data.model.user_joined_game_server import UserJoinedGameServer | ||||
| from bot_graphql.abc.data_query_abc import DataQueryABC | ||||
|  | ||||
|  | ||||
| class UserJoinedGameServerQuery(DataQueryABC): | ||||
|     def __init__(self, bot: DiscordBotServiceABC): | ||||
|         DataQueryABC.__init__(self, "UserJoinedGameServer") | ||||
|  | ||||
|         self._bot = bot | ||||
|  | ||||
|         self.set_field("id", self.resolve_id) | ||||
|         self.set_field("gameServer", self.resolve_game_server) | ||||
|         self.set_field("user", self.resolve_user) | ||||
|         self.set_field("joinedOn", self.resolve_joined_on) | ||||
|         self.set_field("leavedOn", self.resolve_leaved_on) | ||||
|  | ||||
|     @staticmethod | ||||
|     def resolve_id(x: UserJoinedGameServer, *_): | ||||
|         return x.id | ||||
|  | ||||
|     @staticmethod | ||||
|     def resolve_game_server(x: UserJoinedGameServer, *_): | ||||
|         return x.game_server | ||||
|  | ||||
|     @staticmethod | ||||
|     def resolve_user(x: UserJoinedGameServer, *_): | ||||
|         return x.user | ||||
|  | ||||
|     @staticmethod | ||||
|     def resolve_joined_on(x: UserJoinedGameServer, *_): | ||||
|         return x.joined_on | ||||
|  | ||||
|     @staticmethod | ||||
|     def resolve_leaved_on(x: UserJoinedGameServer, *_): | ||||
|         return x.leaved_on | ||||
| @@ -1,10 +1,12 @@ | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
|  | ||||
| from bot_core.abc.client_utils_abc import ClientUtilsABC | ||||
| from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC | ||||
| from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC | ||||
| from bot_data.model.user import User | ||||
| from bot_graphql.abc.data_query_abc import DataQueryABC | ||||
| from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter | ||||
| from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter | ||||
| from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter | ||||
| from modules.level.service.level_service import LevelService | ||||
| @@ -18,12 +20,14 @@ class UserQuery(DataQueryABC): | ||||
|         client_utils: ClientUtilsABC, | ||||
|         ujs: UserJoinedServerRepositoryABC, | ||||
|         ujvs: UserJoinedVoiceChannelRepositoryABC, | ||||
|         user_joined_game_server: UserJoinedGameServerRepositoryABC, | ||||
|     ): | ||||
|         DataQueryABC.__init__(self, "User") | ||||
|  | ||||
|         self._bot = bot | ||||
|         self._levels = levels | ||||
|         self._client_utils = client_utils | ||||
|         self._user_joined_game_server = user_joined_game_server | ||||
|         self._ujs = ujs | ||||
|         self._ujvs = ujvs | ||||
|  | ||||
| @@ -31,6 +35,7 @@ class UserQuery(DataQueryABC): | ||||
|         self.set_field("discordId", self.resolve_discord_id) | ||||
|         self.set_field("name", self.resolve_name) | ||||
|         self.set_field("xp", self.resolve_xp) | ||||
|         self.set_field("minecraftId", self.resolve_minecraft_id) | ||||
|         self.set_field("ontime", self.resolve_ontime) | ||||
|         self.set_field("level", self.resolve_level) | ||||
|         self.add_collection( | ||||
| @@ -43,6 +48,11 @@ class UserQuery(DataQueryABC): | ||||
|             lambda user, *_: self._ujvs.get_user_joined_voice_channels_by_user_id(user.user_id), | ||||
|             UserJoinedVoiceChannelFilter, | ||||
|         ) | ||||
|         self.add_collection( | ||||
|             "userJoinedGameServer", | ||||
|             lambda user, *_: self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.user_id), | ||||
|             UserJoinedGameServerFilter, | ||||
|         ) | ||||
|         self.set_field("server", self.resolve_server) | ||||
|  | ||||
|     @staticmethod | ||||
| @@ -62,6 +72,10 @@ class UserQuery(DataQueryABC): | ||||
|     def resolve_xp(user: User, *_): | ||||
|         return user.xp | ||||
|  | ||||
|     @staticmethod | ||||
|     def resolve_minecraft_id(user: User, *_): | ||||
|         return user.minecraft_id | ||||
|  | ||||
|     def resolve_ontime(self, user: User, *_): | ||||
|         return self._client_utils.get_ontime_for_user(user) | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,7 @@ from bot_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| from bot_data.abc.level_repository_abc import LevelRepositoryABC | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC | ||||
| from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
| @@ -13,6 +14,7 @@ from bot_graphql.filter.client_filter import ClientFilter | ||||
| from bot_graphql.filter.level_filter import LevelFilter | ||||
| from bot_graphql.filter.server_filter import ServerFilter | ||||
| from bot_graphql.filter.user_filter import UserFilter | ||||
| from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter | ||||
| from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter | ||||
| from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter | ||||
|  | ||||
| @@ -27,6 +29,7 @@ class Query(QueryABC): | ||||
|         servers: ServerRepositoryABC, | ||||
|         user_joined_servers: UserJoinedServerRepositoryABC, | ||||
|         user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC, | ||||
|         user_joined_game_server: UserJoinedGameServerRepositoryABC, | ||||
|         users: UserRepositoryABC, | ||||
|     ): | ||||
|         QueryABC.__init__(self, "Query") | ||||
| @@ -37,6 +40,7 @@ class Query(QueryABC): | ||||
|         self._servers = servers | ||||
|         self._user_joined_servers = user_joined_servers | ||||
|         self._user_joined_voice_channels = user_joined_voice_channel | ||||
|         self._user_joined_game_server = user_joined_game_server | ||||
|         self._users = users | ||||
|  | ||||
|         self.add_collection("autoRole", lambda *_: self._auto_roles.get_auto_roles(), AutoRoleFilter) | ||||
| @@ -53,4 +57,9 @@ class Query(QueryABC): | ||||
|             lambda *_: self._user_joined_voice_channels.get_user_joined_voice_channels(), | ||||
|             UserJoinedVoiceChannelFilter, | ||||
|         ) | ||||
|         self.add_collection( | ||||
|             "userJoinedGameServer", | ||||
|             lambda *_: self._user_joined_game_server.get_user_joined_game_servers(), | ||||
|             UserJoinedGameServerFilter, | ||||
|         ) | ||||
|         self.add_collection("user", lambda *_: self._users.get_users(), UserFilter) | ||||
|   | ||||
| @@ -14,6 +14,8 @@ from modules.base.command.mass_move_command import MassMoveCommand | ||||
| from modules.base.command.ping_command import PingCommand | ||||
| from modules.base.command.presence_command import PresenceCommand | ||||
| from modules.base.command.purge_command import PurgeCommand | ||||
| from modules.base.command.register_group import RegisterGroup | ||||
| from modules.base.command.unregister_group import UnregisterGroup | ||||
| from modules.base.command.user_group import UserGroup | ||||
| from modules.base.events.base_on_command_error_event import BaseOnCommandErrorEvent | ||||
| from modules.base.events.base_on_command_event import BaseOnCommandEvent | ||||
| @@ -53,6 +55,8 @@ class BaseModule(ModuleABC): | ||||
|  | ||||
|         self._dc.add_command(PurgeCommand) | ||||
|         self._dc.add_command(UserGroup) | ||||
|         self._dc.add_command(RegisterGroup) | ||||
|         self._dc.add_command(UnregisterGroup) | ||||
|         # events | ||||
|         self._dc.add_event(DiscordEventTypesEnum.on_command.value, BaseOnCommandEvent) | ||||
|         self._dc.add_event(DiscordEventTypesEnum.on_command_error.value, BaseOnCommandErrorEvent) | ||||
|   | ||||
							
								
								
									
										85
									
								
								kdb-bot/src/modules/base/command/register_group.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								kdb-bot/src/modules/base/command/register_group.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| import discord | ||||
| import requests | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_discord.command import DiscordCommandABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_translation import TranslatePipe | ||||
| from discord.ext import commands | ||||
| from discord.ext.commands import Context | ||||
|  | ||||
| from bot_core.abc.client_utils_abc import ClientUtilsABC | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
| from bot_core.helper.command_checks import CommandChecks | ||||
| from bot_core.logging.command_logger import CommandLogger | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
|  | ||||
|  | ||||
| class RegisterGroup(DiscordCommandABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         logger: CommandLogger, | ||||
|         message_service: MessageServiceABC, | ||||
|         bot: DiscordBotServiceABC, | ||||
|         client_utils: ClientUtilsABC, | ||||
|         servers: ServerRepositoryABC, | ||||
|         users: UserRepositoryABC, | ||||
|         db: DatabaseContextABC, | ||||
|         t: TranslatePipe, | ||||
|     ): | ||||
|         DiscordCommandABC.__init__(self) | ||||
|  | ||||
|         self._logger = logger | ||||
|         self._message_service = message_service | ||||
|         self._bot = bot | ||||
|         self._client_utils = client_utils | ||||
|         self._servers = servers | ||||
|         self._users = users | ||||
|         self._db = db | ||||
|         self._t = t | ||||
|  | ||||
|         self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") | ||||
|  | ||||
|     @commands.hybrid_group() | ||||
|     @commands.guild_only() | ||||
|     async def register(self, ctx: Context): | ||||
|         pass | ||||
|  | ||||
|     @register.command() | ||||
|     @commands.guild_only() | ||||
|     @CommandChecks.check_is_ready() | ||||
|     @CommandChecks.check_is_member_moderator() | ||||
|     async def minecraft(self, ctx: Context, member: discord.Member, name: str): | ||||
|         self._logger.debug(__name__, f"Received command register minecraft {ctx}") | ||||
|  | ||||
|         minecraft_id = None | ||||
|         try: | ||||
|             self._logger.debug(__name__, f"Try to get minecraft id for {name}") | ||||
|             response = requests.get(url=f"https://api.mojang.com/users/profiles/minecraft/{name}") | ||||
|             if len(response.content) == 0: | ||||
|                 await self._message_service.send_interaction_msg( | ||||
|                     ctx.interaction, self._t.transform("modules.base.register.not_found") | ||||
|                 ) | ||||
|                 return | ||||
|  | ||||
|             minecraft_id = response.json()["id"] | ||||
|         except Exception as e: | ||||
|             self._logger.error(__name__, f"Get minecraft id for {name} failed", e) | ||||
|             await self._message_service.send_interaction_msg( | ||||
|                 ctx.interaction, self._t.transform("modules.base.register.not_found") | ||||
|             ) | ||||
|  | ||||
|         if minecraft_id is None: | ||||
|             return | ||||
|  | ||||
|         server = self._servers.get_server_by_discord_id(ctx.guild.id) | ||||
|         user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) | ||||
|         user.minecraft_id = minecraft_id | ||||
|         self._users.update_user(user) | ||||
|         self._db.save_changes() | ||||
|  | ||||
|         await self._message_service.send_interaction_msg( | ||||
|             ctx.interaction, self._t.transform("modules.base.register.success") | ||||
|         ) | ||||
|  | ||||
|         self._logger.trace(__name__, f"Finished register minecraft command") | ||||
							
								
								
									
										64
									
								
								kdb-bot/src/modules/base/command/unregister_group.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								kdb-bot/src/modules/base/command/unregister_group.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| import discord | ||||
| from cpl_core.database.context import DatabaseContextABC | ||||
| from cpl_discord.command import DiscordCommandABC | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
| from cpl_translation import TranslatePipe | ||||
| from discord.ext import commands | ||||
| from discord.ext.commands import Context | ||||
|  | ||||
| from bot_core.abc.client_utils_abc import ClientUtilsABC | ||||
| from bot_core.abc.message_service_abc import MessageServiceABC | ||||
| from bot_core.helper.command_checks import CommandChecks | ||||
| from bot_core.logging.command_logger import CommandLogger | ||||
| from bot_data.abc.server_repository_abc import ServerRepositoryABC | ||||
| from bot_data.abc.user_repository_abc import UserRepositoryABC | ||||
|  | ||||
|  | ||||
| class UnregisterGroup(DiscordCommandABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         logger: CommandLogger, | ||||
|         message_service: MessageServiceABC, | ||||
|         bot: DiscordBotServiceABC, | ||||
|         client_utils: ClientUtilsABC, | ||||
|         servers: ServerRepositoryABC, | ||||
|         users: UserRepositoryABC, | ||||
|         db: DatabaseContextABC, | ||||
|         t: TranslatePipe, | ||||
|     ): | ||||
|         DiscordCommandABC.__init__(self) | ||||
|  | ||||
|         self._logger = logger | ||||
|         self._message_service = message_service | ||||
|         self._bot = bot | ||||
|         self._client_utils = client_utils | ||||
|         self._servers = servers | ||||
|         self._users = users | ||||
|         self._db = db | ||||
|         self._t = t | ||||
|  | ||||
|         self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") | ||||
|  | ||||
|     @commands.hybrid_group() | ||||
|     @commands.guild_only() | ||||
|     async def unregister(self, ctx: Context): | ||||
|         pass | ||||
|  | ||||
|     @unregister.command() | ||||
|     @commands.guild_only() | ||||
|     @CommandChecks.check_is_ready() | ||||
|     @CommandChecks.check_is_member_moderator() | ||||
|     async def minecraft(self, ctx: Context, member: discord.Member): | ||||
|         self._logger.debug(__name__, f"Received command register minecraft {ctx}") | ||||
|  | ||||
|         server = self._servers.get_server_by_discord_id(ctx.guild.id) | ||||
|         user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) | ||||
|         user.minecraft_id = None | ||||
|         self._users.update_user(user) | ||||
|         self._db.save_changes() | ||||
|  | ||||
|         await self._message_service.send_interaction_msg( | ||||
|             ctx.interaction, self._t.transform("modules.base.unregister.success") | ||||
|         ) | ||||
|  | ||||
|         self._logger.trace(__name__, f"Finished register minecraft command") | ||||
| @@ -11,6 +11,7 @@ from bot_core.logging.database_logger import DatabaseLogger | ||||
| from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe | ||||
| from bot_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC | ||||
| from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC | ||||
| from bot_data.abc.user_joined_voice_channel_repository_abc import ( | ||||
|     UserJoinedVoiceChannelRepositoryABC, | ||||
| @@ -41,6 +42,7 @@ class DatabaseOnReadyEvent(OnReadyABC): | ||||
|         known_users: KnownUserRepositoryABC, | ||||
|         user_joins: UserJoinedServerRepositoryABC, | ||||
|         user_joins_vc: UserJoinedVoiceChannelRepositoryABC, | ||||
|         user_joined_gs: UserJoinedGameServerRepositoryABC, | ||||
|         dtp: DateTimeOffsetPipe, | ||||
|     ): | ||||
|         self._config = config | ||||
| @@ -55,6 +57,7 @@ class DatabaseOnReadyEvent(OnReadyABC): | ||||
|         self._known_users = known_users | ||||
|         self._user_joins = user_joins | ||||
|         self._user_joins_vc = user_joins_vc | ||||
|         self._user_joined_gs = user_joined_gs | ||||
|         self._dtp = dtp | ||||
|  | ||||
|         OnReadyABC.__init__(self) | ||||
| @@ -327,6 +330,48 @@ class DatabaseOnReadyEvent(OnReadyABC): | ||||
|             except Exception as e: | ||||
|                 self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e) | ||||
|  | ||||
|     def _check_user_joined_gs(self): | ||||
|         self._logger.debug(__name__, f"Start checking UserJoinedGameServer 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 member in guild.members: | ||||
|                     if member.bot: | ||||
|                         self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") | ||||
|                         continue | ||||
|  | ||||
|                     user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) | ||||
|                     if user is None: | ||||
|                         self._logger.fatal(__name__, f"User not found in database: {member.id}") | ||||
|  | ||||
|                     joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.user_id) | ||||
|                     if joins is None or len(joins) == 0: | ||||
|                         continue | ||||
|  | ||||
|                     for join in joins: | ||||
|                         self._logger.warn( | ||||
|                             __name__, | ||||
|                             f"Active UserJoinedGameServer found in database: {guild.id}:{member.id}@{join.joined_on}", | ||||
|                         ) | ||||
|                         join.leaved_on = datetime.now() | ||||
|                         settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}") | ||||
|  | ||||
|                         if ( | ||||
|                             (join.leaved_on - join.joined_on).total_seconds() / 60 / 60 | ||||
|                         ) > settings.max_voice_state_hours: | ||||
|                             join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours) | ||||
|  | ||||
|                         self._user_joined_gs.update_user_joined_game_server(join) | ||||
|                         # todo: maybe add XP | ||||
|                         self._db_context.save_changes() | ||||
|             except Exception as e: | ||||
|                 self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e) | ||||
|  | ||||
|     async def on_ready(self): | ||||
|         self._logger.debug(__name__, f"Module {type(self)} started") | ||||
|  | ||||
| @@ -338,6 +383,7 @@ class DatabaseOnReadyEvent(OnReadyABC): | ||||
|         self._check_users() | ||||
|         self._check_user_joins() | ||||
|         self._check_user_joins_vc() | ||||
|         self._check_user_joined_gs() | ||||
|  | ||||
|         self._validate_init_time() | ||||
|         self._logger.trace(__name__, f"Module {type(self)} stopped") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user