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 cpl_core.logging import LoggerABC
from gismo_core.abc.bot_service_abc import BotServiceABC 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_core.service.bot_service import BotService
from gismo_data.service.migration_service import MigrationService from gismo_data.service.migration_service import MigrationService
@ -16,14 +19,18 @@ class Gismo(ApplicationABC):
self._bot: BotService = services.get_service(BotServiceABC) self._bot: BotService = services.get_service(BotServiceABC)
self._logger: LoggerABC = services.get_service(LoggerABC) 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): 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): async def main(self):
try: try:
self._migrations.migrate()
self._logger.trace(__name__, f'Try to start {BotService}') self._logger.trace(__name__, f'Try to start {BotService}')
await self._bot.start_async() await self._bot.start_async()
except Exception as e: 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.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"sh_cpl-core>=2021.11.0.post3", "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", "PythonVersion": ">=3.9.2",
"PythonPath": { "PythonPath": {

View File

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

View File

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

View File

@ -1,7 +1,7 @@
from abc import ABC, ABCMeta from abc import ABC, ABCMeta
from datetime import datetime from datetime import datetime
import json import json
from typing import Optional, Sequence, Union from typing import Optional, Sequence, Union, Type
import discord import discord
from cpl_core.configuration import ConfigurationModelABC, ConfigurationABC from cpl_core.configuration import ConfigurationModelABC, ConfigurationABC
@ -69,37 +69,14 @@ class ModuleService(ModuleServiceABC, commands.Cog, metaclass=CommandsMeta):
self._config = config self._config = config
self._services = services self._services = services
self._env = env self._env = env
self._modules: List[ModuleABC] = List() self._modules_types: List[Type[ModuleABC]] = List()
self._modules.extend(ModuleABC.__subclasses__()) self._modules_types.extend(ModuleABC.__subclasses__())
self._modules: List[ModuleABC] = List(ModuleABC)
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))
async def _handle_event(self, event: type, *args): async def _handle_event(self, event: type, *args):
self._logger.debug(__name__, f'Start {event} modules') 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: if modules.count() < 1:
self._logger.debug(__name__, f'Stopped {event} modules') 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.error(__name__, f'Start {event} modules failed', e)
self._logger.debug(__name__, f'Stopped {event} modules') 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() @commands.Cog.listener()
async def on_connect(self): async def on_connect(self):

View File

@ -23,6 +23,9 @@ class UserJoinedVoiceChannelRepositoryABC(ABC):
@abstractmethod @abstractmethod
def find_active_user_joined_voice_channel_by_user_id(self, user_id: int) -> Optional[UserJoinedVoiceChannel]: pass 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 @abstractmethod
def add_user_joined_voice_channel(self, user_joined_voice_channel: UserJoinedVoiceChannel): pass 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.database.context import DatabaseContextABC
from cpl_core.logging import LoggerABC 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.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.model.user_joined_voice_channel import UserJoinedVoiceChannel
from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC
@ -93,6 +92,23 @@ class UserJoinedVoiceChannelRepositoryService(UserJoinedVoiceChannelRepositoryAB
result[5], result[5],
id=result[0] 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): 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._logger.trace(__name__, f'Send SQL command: {user_joined_voice_channel.insert_string}')

View File

@ -1,5 +1,5 @@
from ctypes import Union from ctypes import Union
from datetime import datetime from datetime import datetime, timedelta
import discord import discord
from cpl_core.configuration import ConfigurationABC from cpl_core.configuration import ConfigurationABC
@ -268,20 +268,21 @@ class Database(ModuleABC, OnReadyABC):
if user is None: if user is None:
self._logger.fatal(__name__, f'User not found in database: {member.id}') 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) joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.user_id)
if join is None: if joins is None or len(joins) == 0:
continue continue
self._logger.warn(__name__, f'Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}') for join in joins:
join.leaved_on = datetime.now() self._logger.warn(__name__, f'Active UserJoinedVoiceChannel found in database: {guild.id}:{member.id}@{join.joined_on}')
settings: BaseSettings = self._config.get_configuration(f'base_{guild.id}') 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)
self._user_joins_vc.update_user_joined_voice_channel(join) if ((join.leaved_on - join.joined_on).total_seconds()/60/60) > settings.max_voice_state_hours:
# todo: maybe add XP join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours)
self._db_context.save_changes()
self._user_joins_vc.update_user_joined_voice_channel(join)
# todo: maybe add XP
self._db_context.save_changes()
for member in guild.members: for member in guild.members:
if member.bot: 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.dependency_injection import ServiceProviderABC
from cpl_core.logging import LoggerABC from cpl_core.logging import LoggerABC
from gismo_data.service.migration_service import MigrationService
class DatabaseExtension(ApplicationExtensionABC): class DatabaseExtension(ApplicationExtensionABC):
@ -15,3 +17,5 @@ class DatabaseExtension(ApplicationExtensionABC):
logger: LoggerABC = services.get_service(LoggerABC) logger: LoggerABC = services.get_service(LoggerABC)
logger.debug(__name__, 'Database extension started') logger.debug(__name__, 'Database extension started')
config.add_configuration('Database_StartTime', str(datetime.now())) config.add_configuration('Database_StartTime', str(datetime.now()))
migrations = services.get_service(MigrationService)
migrations.migrate()