Improved module, event and settings loading

This commit is contained in:
Sven Heidemann 2022-01-15 11:47:59 +01:00
parent 9eef94baf2
commit 234a9a382a
10 changed files with 91 additions and 61 deletions

View File

@ -5,6 +5,9 @@ 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.abc.module_service_abc import ModuleServiceABC
from gismo_core.configuration.bot_settings import BotSettings
from gismo_core.configuration.server_settings import ServerSettings
from gismo_core.service.bot_service import BotService
from gismo_data.service.migration_service import MigrationService
@ -16,14 +19,18 @@ class Gismo(ApplicationABC):
self._bot: BotService = services.get_service(BotServiceABC)
self._logger: LoggerABC = services.get_service(LoggerABC)
self._migrations: MigrationService = services.get_service(MigrationService)
self._bot_settings: BotSettings = config.get_configuration(BotSettings)
async def configure(self):
pass
self._logger.debug(__name__, 'Try to load discord server configs')
for server in self._bot_settings.servers:
server: ServerSettings = server
self._logger.trace(__name__, f'Try to load config for server: {server.id}')
self._configuration.add_configuration(f'DSERVER_{server.id}', server)
self._logger.trace(__name__, f'Loaded config for server: {server.id}')
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:

@ -1 +1 @@
Subproject commit 3d4e93d4d658e1c6c571756f99a3297efb8a7d64
Subproject commit ed5887b6d068d33e686347081630b18d896ece4c

View File

@ -17,8 +17,8 @@
"LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [
"sh_cpl-core>=2021.11.0.post3",
"sh_cpl-query>=2021.11.0.post2",
"discord.py==1.7.3"
"discord.py==1.7.3",
"sh_cpl-query==2021.11.0.post3"
],
"PythonVersion": ">=3.9.2",
"PythonPath": {

View File

@ -9,6 +9,9 @@ class ModuleServiceABC(ABC):
@abstractmethod
def __init__(self): pass
@abstractmethod
def load_modules(self): pass
@abstractmethod
async def on_connect(self): pass

View File

@ -25,7 +25,6 @@ class BotService(BotServiceABC, commands.Bot):
logging_st: LoggingSettings,
):
# services
self._config = config
self._logger = logger
self._modules = modules
self._env = env
@ -33,7 +32,6 @@ class BotService(BotServiceABC, commands.Bot):
# settings
self._discord_settings = discord_settings
self._bot_settings: BotSettings = bot_settings
# setup super
commands.Bot.__init__(self, command_prefix=bot_settings.prefix, help_command=None, intents=discord.Intents().all())
@ -41,8 +39,8 @@ class BotService(BotServiceABC, commands.Bot):
async def start_async(self):
self._logger.trace(__name__, 'Try to connect to discord')
self.add_cog(self._modules)
self._modules.load_modules()
await self.start(self._discord_settings.token)
# continue at on_ready
@ -56,16 +54,11 @@ class BotService(BotServiceABC, commands.Bot):
async def on_ready(self):
self._logger.info(__name__, 'Connected to discord')
self._logger.debug(__name__, 'Try to load discord server configs')
for server in self._bot_settings.servers:
server: ServerSettings = server
self._logger.trace(__name__, f'Try to load config for server: {server.id}')
self._config.add_configuration(f'DSERVER_{server.id}', server)
self._logger.trace(__name__, f'Loaded config for server: {server.id}')
self._logger.header(f'{self.user.name}:')
if self._logging_st.console.value >= LoggingLevelEnum.INFO.value:
Console.banner(self._env.application_name if self._env.application_name != '' else 'Gismo')
self.add_cog(self._modules)
await self._modules.on_ready()

View File

@ -1,7 +1,7 @@
from abc import ABC, ABCMeta
from datetime import datetime
import json
from typing import Optional, Sequence, Union
from typing import Optional, Sequence, Union, Type
import discord
from cpl_core.configuration import ConfigurationModelABC, ConfigurationABC
@ -69,37 +69,14 @@ class ModuleService(ModuleServiceABC, commands.Cog, metaclass=CommandsMeta):
self._config = config
self._services = services
self._env = env
self._modules: List[ModuleABC] = List()
self._modules.extend(ModuleABC.__subclasses__())
def _get_modules(self, t: type) -> OrderedIterableABC:
module_types = self._modules.where(lambda m: issubclass(m, t))
modules = List(t)
for module_type in module_types:
module: ModuleABC = self._services.get_service(module_type)
if module is None:
self._logger.warn(__name__, f'Module {module_type} not found in services!')
break
if len(module.settings_types) > 0:
for settings_type in module.settings_types:
settings_name = settings_type.__name__.split('Settings')[0]
with open(f'config/{String.convert_to_snake_case(settings_name).lower()}.json', encoding='utf-8') as cfg:
json_cfg = json.load(cfg)
for index in json_cfg:
settings: ConfigurationModelABC = settings_type()
settings.from_dict(json_cfg[index])
self._config.add_configuration(f'{type(module).__name__}_{index}', settings)
self._logger.debug(__name__, f'Added config: {type(module).__name__}_{index}')
modules.append(module)
return modules.order_by(lambda m: m.get_priority(t))
self._modules_types: List[Type[ModuleABC]] = List()
self._modules_types.extend(ModuleABC.__subclasses__())
self._modules: List[ModuleABC] = List(ModuleABC)
async def _handle_event(self, event: type, *args):
self._logger.debug(__name__, f'Start {event} modules')
modules = self._get_modules(event)
# modules = self._get_modules(event)
modules = self._modules.where(lambda m: isinstance(m, event)).order_by(lambda m: m.get_priority(event))
if modules.count() < 1:
self._logger.debug(__name__, f'Stopped {event} modules')
@ -118,6 +95,32 @@ class ModuleService(ModuleServiceABC, commands.Cog, metaclass=CommandsMeta):
self._logger.error(__name__, f'Start {event} modules failed', e)
self._logger.debug(__name__, f'Stopped {event} modules')
def load_modules(self):
self._logger.debug(__name__, f'Start loading modules')
for module_type in self._modules_types:
module: ModuleABC = self._services.get_service(module_type)
if module is None:
self._logger.warn(__name__, f'Module {module_type} not found in services!')
break
loaded_settings: list[str] = []
for settings_type in module.settings_types:
settings_name = settings_type.__name__.split('Settings')[0]
if settings_name in loaded_settings:
continue
with open(f'config/{String.convert_to_snake_case(settings_name).lower()}.json', encoding='utf-8') as cfg:
json_cfg = json.load(cfg)
for index in json_cfg:
settings: ConfigurationModelABC = settings_type()
settings.from_dict(json_cfg[index])
self._config.add_configuration(f'{type(module).__name__}_{index}', settings)
self._logger.debug(__name__, f'Added config: {type(module).__name__}_{index}')
loaded_settings.append(settings_name)
self._modules.append(module)
@commands.Cog.listener()
async def on_connect(self):

View File

@ -23,6 +23,9 @@ class UserJoinedVoiceChannelRepositoryABC(ABC):
@abstractmethod
def find_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> Optional[UserJoinedVoiceChannel]: pass
@abstractmethod
def find_active_user_joined_voice_channels_by_user_id(self, user_id: int) -> List[Optional[UserJoinedVoiceChannel]]: pass
@abstractmethod
def add_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass

View File

@ -2,9 +2,8 @@ from typing import Optional
from cpl_core.database.context import DatabaseContextABC
from cpl_core.logging import LoggerABC
from cpl_query.extension import List
from cpl_query.extension import List, IterableABC
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
@ -93,6 +92,23 @@ class UserJoinedVoiceChannelRepositoryService(UserJoinedVoiceChannelRepositoryAB
result[5],
id=result[0]
)
def find_active_user_joined_voice_channels_by_user_id(self, user_id: int) -> List[Optional[UserJoinedVoiceChannel]]:
self._logger.trace(__name__, f'Send SQL command: {UserJoinedVoiceChannel.get_select_by_user_id_string(user_id)}')
result = List(UserJoinedVoiceChannel)
db_results = self._context.select(UserJoinedVoiceChannel.get_select_active_by_user_id_string(user_id))
for db_result in db_results:
result.append(UserJoinedVoiceChannel(
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_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel):
self._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.insert_string}')

View File

@ -1,5 +1,5 @@
from ctypes import Union
from datetime import datetime
from datetime import datetime, timedelta
import discord
from cpl_core.configuration import ConfigurationABC
@ -268,20 +268,21 @@ class Database(ModuleABC, OnReadyABC):
if user is None:
self._logger.fatal(__name__, f'User not found in database: {member.id}')
join = self._user_joins_vc.find_active_user_joined_voice_channel_by_user_id(user.user_id)
if join is None:
joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.user_id)
if joins is None or len(joins) == 0:
continue
self._logger.warn(__name__, f'Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}')
join.leaved_on = datetime.now()
settings: BaseSettings = self._config.get_configuration(f'base_{guild.id}')
if ((join.leaved_on - join.joined_on).total_seconds()/60/60) > settings.max_voice_state_hours:
join.leaved_on = join.joined_on + datetime.timedelta(hours=settings.max_voice_state_hours)
for join in joins:
self._logger.warn(__name__, f'Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}')
join.leaved_on = datetime.now()
settings: BaseSettings = self._config.get_configuration(f'Base_{guild.id}')
self._user_joins_vc.update_user_joined_voice_channel(join)
# todo: maybe add XP
self._db_context.save_changes()
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_joins_vc.update_user_joined_voice_channel(join)
# todo: maybe add XP
self._db_context.save_changes()
for member in guild.members:
if member.bot:

View File

@ -5,6 +5,8 @@ from cpl_core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceProviderABC
from cpl_core.logging import LoggerABC
from gismo_data.service.migration_service import MigrationService
class DatabaseExtension(ApplicationExtensionABC):
@ -15,3 +17,5 @@ class DatabaseExtension(ApplicationExtensionABC):
logger: LoggerABC = services.get_service(LoggerABC)
logger.debug(__name__, 'Database extension started')
config.add_configuration('Database_StartTime', str(datetime.now()))
migrations = services.get_service(MigrationService)
migrations.migrate()