diff --git a/kdb-bot/src/bot/application.py b/kdb-bot/src/bot/application.py index 4198de6b..ca3e0976 100644 --- a/kdb-bot/src/bot/application.py +++ b/kdb-bot/src/bot/application.py @@ -10,6 +10,7 @@ from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSet from bot_api.api_thread import ApiThread from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings +from bot_core.service.data_integrity_service import DataIntegrityService class Application(DiscordBotApplicationABC): @@ -21,6 +22,7 @@ class Application(DiscordBotApplicationABC): # cpl-core self._logger: LoggerABC = services.get_service(LoggerABC) + self._data_integrity: DataIntegrityService = services.get_service(DataIntegrityService) # cpl-discord self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC) self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings) @@ -69,6 +71,7 @@ class Application(DiscordBotApplicationABC): self._api.stop() await self._bot.close() + self._data_integrity.check_data_integrity(is_for_shutdown=True) self._logger.info(__name__, f"Stopped {DiscordBotService.__name__}") except Exception as e: self._logger.error(__name__, "stop failed", e) @@ -76,4 +79,4 @@ class Application(DiscordBotApplicationABC): Console.write_line() def is_restart(self): - return True if self._configuration.get_configuration("IS_RESTART") == "true" else False # + return True if self._configuration.get_configuration("IS_RESTART") == "true" else False diff --git a/kdb-bot/src/bot_core/core_module.py b/kdb-bot/src/bot_core/core_module.py index 001dc36c..b7397b36 100644 --- a/kdb-bot/src/bot_core/core_module.py +++ b/kdb-bot/src/bot_core/core_module.py @@ -11,6 +11,7 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.events.core_on_ready_event import CoreOnReadyEvent from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe from bot_core.service.client_utils_service import ClientUtilsService +from bot_core.service.data_integrity_service import DataIntegrityService from bot_core.service.message_service import MessageService @@ -24,6 +25,7 @@ class CoreModule(ModuleABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services.add_transient(MessageServiceABC, MessageService) services.add_transient(ClientUtilsABC, ClientUtilsService) + services.add_transient(DataIntegrityService) # pipes services.add_transient(DateTimeOffsetPipe) diff --git a/kdb-bot/src/bot_core/service/data_integrity_service.py b/kdb-bot/src/bot_core/service/data_integrity_service.py new file mode 100644 index 00000000..c3f76912 --- /dev/null +++ b/kdb-bot/src/bot_core/service/data_integrity_service.py @@ -0,0 +1,373 @@ +from datetime import datetime, timedelta +from typing import Union + +import discord +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +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, +) +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.client import Client +from bot_data.model.known_user import KnownUser +from bot_data.model.server import Server +from bot_data.model.user import User +from bot_data.model.user_joined_server import UserJoinedServer +from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_data.service.seeder_service import SeederService +from bot_data.service.user_repository_service import ServerRepositoryABC +from modules.base.configuration.base_server_settings import BaseServerSettings + + +class DataIntegrityService: + def __init__( + self, + config: ConfigurationABC, + logger: DatabaseLogger, + seeder: SeederService, + bot: DiscordBotServiceABC, + db_context: DatabaseContextABC, + server_repo: ServerRepositoryABC, + user_repo: UserRepositoryABC, + client_repo: ClientRepositoryABC, + known_users: KnownUserRepositoryABC, + user_joins: UserJoinedServerRepositoryABC, + user_joins_vc: UserJoinedVoiceChannelRepositoryABC, + user_joined_gs: UserJoinedGameServerRepositoryABC, + dtp: DateTimeOffsetPipe, + ): + self._config = config + + self._logger = logger + self._seeder = seeder + self._bot = bot + self._db_context = db_context + self._servers = server_repo + self._users = user_repo + self._clients = client_repo + 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 + + self._is_for_shutdown = False + + def _check_known_users(self): + self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}") + for u in self._bot.users: + u: discord.User = u + try: + if u.bot: + self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") + continue + + user = self._known_users.find_user_by_discord_id(u.id) + if user is not None: + continue + + self._logger.warn(__name__, f"Unknown user: {u.id}") + self._logger.debug(__name__, f"Add user: {u.id}") + self._known_users.add_user(KnownUser(u.id)) + self._db_context.save_changes() + + user = self._known_users.find_user_by_discord_id(u.id) + if user is None: + self._logger.fatal(__name__, f"Cannot add user: {u.id}") + + self._logger.debug(__name__, f"Added user: {u.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get user", e) + + def _check_servers(self): + self._logger.debug(__name__, f"Start checking Servers table") + for g in self._bot.guilds: + g: discord.Guild = g + try: + server = self._servers.find_server_by_discord_id(g.id) + if server is not None: + continue + + self._logger.warn(__name__, f"Server not found in database: {g.id}") + self._logger.debug(__name__, f"Add server: {g.id}") + self._servers.add_server(Server(g.id)) + self._db_context.save_changes() + + server = self._servers.find_server_by_discord_id(g.id) + if server is None: + self._logger.fatal(__name__, f"Cannot add server: {g.id}") + + self._logger.debug(__name__, f"Added server: {g.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get server", e) + + results = self._servers.get_servers() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Servers is empty!") + + def _check_clients(self): + self._logger.debug(__name__, f"Start checking Clients table") + for g in self._bot.guilds: + g: discord.Guild = g + try: + server: Server = self._servers.find_server_by_discord_id(g.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {g.id}") + + client = self._clients.find_client_by_server_id(server.id) + if client is not None: + continue + + self._logger.warn( + __name__, + f"Client for server {g.id} not found in database: {self._bot.user.id}", + ) + self._logger.debug(__name__, f"Add client: {self._bot.user.id}") + self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server)) + self._db_context.save_changes() + + client = self._clients.find_client_by_server_id(server.id) + if client is None: + self._logger.fatal( + __name__, + f"Cannot add client {self._bot.user.id} for server {g.id}", + ) + + self._logger.debug(__name__, f"Added client: {g.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get client", e) + + results = self._servers.get_servers() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Servers is empty!") + + def _check_users(self): + self._logger.debug(__name__, f"Start checking Users table") + for g in self._bot.guilds: + g: discord.Guild = g + + try: + server = self._servers.find_server_by_discord_id(g.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {g.id}") + + for u in g.members: + u: Union[discord.Member, discord.User] = u + if u.bot: + self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) + if user is not None: + continue + + self._logger.warn(__name__, f"User not found in database: {u.id}") + self._logger.debug(__name__, f"Add user: {u.id}") + self._users.add_user(User(u.id, 0, server)) + self._db_context.save_changes() + + self._logger.debug(__name__, f"Added User: {u.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get User", e) + + results = self._users.get_users() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Users is empty!") + + def _check_user_joins(self): + self._logger.debug(__name__, f"Start checking UserJoinedServers table") + for guild in self._bot.guilds: + guild: discord.Guild = guild + + server = self._servers.find_server_by_discord_id(guild.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {guild.id}") + + try: + for u in guild.members: + u: discord.User = u + if u.bot: + self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {u.id}") + + join = self._user_joins.find_active_user_joined_server_by_user_id(user.id) + if join is not None: + continue + + m: discord.Member = u + self._logger.warn( + __name__, + f"Active UserJoinedServer not found in database: {guild.id}:{u.id}@{m.joined_at}", + ) + self._logger.debug( + __name__, + f"Add UserJoinedServer: {guild.id}:{u.id}@{m.joined_at}", + ) + self._user_joins.add_user_joined_server( + UserJoinedServer(user, self._dtp.transform(m.joined_at), None) + ) + self._db_context.save_changes() + + self._logger.debug(__name__, f"Added UserJoinedServer: {u.id}") + except Exception as e: + self._logger.error(__name__, f"Cannot get UserJoinedServer", e) + + results = self._users.get_users() + if results is None or len(results) == 0: + self._logger.error(__name__, f"Table Users is empty!") + + joins = self._user_joins.get_user_joined_servers() + for join in joins: + join: UserJoinedServer = join + if join.user.server.discord_id != guild.id: + continue + + if join.leaved_on is not None: + continue + + dc_user = guild.get_member(join.user.discord_id) + if dc_user is None: + self._logger.warn( + __name__, + f"User {join.user.discord_id} already left the server.", + ) + join.leaved_on = datetime.now() + self._user_joins.update_user_joined_server(join) + + self._db_context.save_changes() + + def _check_user_joins_vc(self): + self._logger.debug(__name__, f"Start checking UserJoinedVoiceChannel table") + for guild in self._bot.guilds: + guild: discord.Guild = guild + settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}") + + 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: + # close open voice states + 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.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {member.id}") + + joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id) + if joins is None or len(joins) == 0: + continue + + 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() + + 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) + + if self._is_for_shutdown: + user.xp = round(join.time * settings.xp_per_ontime_hour) + self._users.update_user(user) + + self._db_context.save_changes() + if self._is_for_shutdown: + return + + # add open voice states + for member in guild.members: + if member.bot: + self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") + continue + + if member.voice is None or member.voice.channel.id in settings.afk_channel_ids: + continue + + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {member.id}") + + join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now()) + self._user_joins_vc.add_user_joined_voice_channel(join) + self._db_context.save_changes() + + 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.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.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) + if self._is_for_shutdown: + user.xp = round(join.time * settings.xp_per_ontime_hour) + self._users.update_user(user) + + self._db_context.save_changes() + except Exception as e: + self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e) + + def check_data_integrity(self, is_for_shutdown=False): + if is_for_shutdown != self._is_for_shutdown: + self._is_for_shutdown = is_for_shutdown + + self._check_known_users() + self._check_servers() + self._check_clients() + self._check_users() + self._check_user_joins() + self._check_user_joins_vc() + self._check_user_joined_gs() diff --git a/kdb-bot/src/modules/database/database_on_ready_event.py b/kdb-bot/src/modules/database/database_on_ready_event.py index 8d512035..d895592d 100644 --- a/kdb-bot/src/modules/database/database_on_ready_event.py +++ b/kdb-bot/src/modules/database/database_on_ready_event.py @@ -1,31 +1,11 @@ -from ctypes import Union -from datetime import datetime, timedelta +from datetime import datetime -import discord from cpl_core.configuration import ConfigurationABC -from cpl_core.database.context import DatabaseContextABC from cpl_discord.events import OnReadyABC -from cpl_discord.service import DiscordBotServiceABC 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, -) -from bot_data.abc.user_repository_abc import UserRepositoryABC -from bot_data.model.client import Client -from bot_data.model.known_user import KnownUser -from bot_data.model.server import Server -from bot_data.model.user import User -from bot_data.model.user_joined_server import UserJoinedServer -from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_core.service.data_integrity_service import DataIntegrityService from bot_data.service.seeder_service import SeederService -from bot_data.service.user_repository_service import ServerRepositoryABC -from modules.base.configuration.base_server_settings import BaseServerSettings class DatabaseOnReadyEvent(OnReadyABC): @@ -34,31 +14,13 @@ class DatabaseOnReadyEvent(OnReadyABC): config: ConfigurationABC, logger: DatabaseLogger, seeder: SeederService, - bot: DiscordBotServiceABC, - db_context: DatabaseContextABC, - server_repo: ServerRepositoryABC, - user_repo: UserRepositoryABC, - client_repo: ClientRepositoryABC, - known_users: KnownUserRepositoryABC, - user_joins: UserJoinedServerRepositoryABC, - user_joins_vc: UserJoinedVoiceChannelRepositoryABC, - user_joined_gs: UserJoinedGameServerRepositoryABC, - dtp: DateTimeOffsetPipe, + data_integrity: DataIntegrityService, ): self._config = config self._logger = logger self._seeder = seeder - self._bot = bot - self._db_context = db_context - self._servers = server_repo - self._users = user_repo - self._clients = client_repo - 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 + self._data_integrity = data_integrity OnReadyABC.__init__(self) self._logger.info(__name__, f"Module {type(self)} loaded") @@ -83,306 +45,10 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.error(__name__, "Database init time calculation failed", e) return - def _check_known_users(self): - self._logger.debug(__name__, f"Start checking KnownUsers table, {len(self._bot.users)}") - for u in self._bot.users: - u: discord.User = u - try: - if u.bot: - self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") - continue - - user = self._known_users.find_user_by_discord_id(u.id) - if user is not None: - continue - - self._logger.warn(__name__, f"Unknown user: {u.id}") - self._logger.debug(__name__, f"Add user: {u.id}") - self._known_users.add_user(KnownUser(u.id)) - self._db_context.save_changes() - - user = self._known_users.find_user_by_discord_id(u.id) - if user is None: - self._logger.fatal(__name__, f"Cannot add user: {u.id}") - - self._logger.debug(__name__, f"Added user: {u.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get user", e) - - def _check_servers(self): - self._logger.debug(__name__, f"Start checking Servers table") - for g in self._bot.guilds: - g: discord.Guild = g - try: - server = self._servers.find_server_by_discord_id(g.id) - if server is not None: - continue - - self._logger.warn(__name__, f"Server not found in database: {g.id}") - self._logger.debug(__name__, f"Add server: {g.id}") - self._servers.add_server(Server(g.id)) - self._db_context.save_changes() - - server = self._servers.find_server_by_discord_id(g.id) - if server is None: - self._logger.fatal(__name__, f"Cannot add server: {g.id}") - - self._logger.debug(__name__, f"Added server: {g.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get server", e) - - results = self._servers.get_servers() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Servers is empty!") - - def _check_clients(self): - self._logger.debug(__name__, f"Start checking Clients table") - for g in self._bot.guilds: - g: discord.Guild = g - try: - server: Server = self._servers.find_server_by_discord_id(g.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {g.id}") - - client = self._clients.find_client_by_server_id(server.id) - if client is not None: - continue - - self._logger.warn( - __name__, - f"Client for server {g.id} not found in database: {self._bot.user.id}", - ) - self._logger.debug(__name__, f"Add client: {self._bot.user.id}") - self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server)) - self._db_context.save_changes() - - client = self._clients.find_client_by_server_id(server.id) - if client is None: - self._logger.fatal( - __name__, - f"Cannot add client {self._bot.user.id} for server {g.id}", - ) - - self._logger.debug(__name__, f"Added client: {g.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get client", e) - - results = self._servers.get_servers() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Servers is empty!") - - def _check_users(self): - self._logger.debug(__name__, f"Start checking Users table") - for g in self._bot.guilds: - g: discord.Guild = g - - try: - server = self._servers.find_server_by_discord_id(g.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {g.id}") - - for u in g.members: - u: Union[discord.Member, discord.User] = u - if u.bot: - self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") - continue - - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) - if user is not None: - continue - - self._logger.warn(__name__, f"User not found in database: {u.id}") - self._logger.debug(__name__, f"Add user: {u.id}") - self._users.add_user(User(u.id, 0, server)) - self._db_context.save_changes() - - self._logger.debug(__name__, f"Added User: {u.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get User", e) - - results = self._users.get_users() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Users is empty!") - - def _check_user_joins(self): - self._logger.debug(__name__, f"Start checking UserJoinedServers table") - for guild in self._bot.guilds: - guild: discord.Guild = guild - - server = self._servers.find_server_by_discord_id(guild.id) - if server is None: - self._logger.fatal(__name__, f"Server not found in database: {guild.id}") - - try: - for u in guild.members: - u: discord.User = u - if u.bot: - self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") - continue - - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) - if user is None: - self._logger.fatal(__name__, f"User not found in database: {u.id}") - - join = self._user_joins.find_active_user_joined_server_by_user_id(user.id) - if join is not None: - continue - - m: discord.Member = u - self._logger.warn( - __name__, - f"Active UserJoinedServer not found in database: {guild.id}:{u.id}@{m.joined_at}", - ) - self._logger.debug( - __name__, - f"Add UserJoinedServer: {guild.id}:{u.id}@{m.joined_at}", - ) - self._user_joins.add_user_joined_server( - UserJoinedServer(user, self._dtp.transform(m.joined_at), None) - ) - self._db_context.save_changes() - - self._logger.debug(__name__, f"Added UserJoinedServer: {u.id}") - except Exception as e: - self._logger.error(__name__, f"Cannot get UserJoinedServer", e) - - results = self._users.get_users() - if results is None or len(results) == 0: - self._logger.error(__name__, f"Table Users is empty!") - - joins = self._user_joins.get_user_joined_servers() - for join in joins: - join: UserJoinedServer = join - if join.user.server.discord_id != guild.id: - continue - - if join.leaved_on is not None: - continue - - dc_user = guild.get_member(join.user.discord_id) - if dc_user is None: - self._logger.warn( - __name__, - f"User {join.user.discord_id} already left the server.", - ) - join.leaved_on = datetime.now() - self._user_joins.update_user_joined_server(join) - - self._db_context.save_changes() - - def _check_user_joins_vc(self): - self._logger.debug(__name__, f"Start checking UserJoinedVoiceChannel table") - for guild in self._bot.guilds: - guild: discord.Guild = guild - settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}") - - 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.id) - if user is None: - self._logger.fatal(__name__, f"User not found in database: {member.id}") - - joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id) - if joins is None or len(joins) == 0: - continue - - 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() - - 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: - self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") - continue - - if member.voice is None or member.voice.channel.id in settings.afk_channel_ids: - continue - - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) - if user is None: - self._logger.fatal(__name__, f"User not found in database: {member.id}") - - join = UserJoinedVoiceChannel(user, member.voice.channel.id, datetime.now()) - self._user_joins_vc.add_user_joined_voice_channel(join) - self._db_context.save_changes() - self._logger.warn(__name__, f"VS {member.voice}") - - 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.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.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") - self._check_known_users() - self._check_servers() - self._check_clients() - self._check_users() - self._check_user_joins() - self._check_user_joins_vc() - self._check_user_joined_gs() - + self._data_integrity.check_data_integrity() await self._seeder.seed() self._validate_init_time()