Added logic to handle xp

This commit is contained in:
Sven Heidemann 2021-12-21 18:12:09 +01:00
parent 286c653252
commit daa031bc57
5 changed files with 118 additions and 7 deletions

View File

@ -26,7 +26,8 @@
"GoodbyeMessage": "", "GoodbyeMessage": "",
"MaxVoiceStateHours": 0, "MaxVoiceStateHours": 0,
"XpPerMessage": 0, "XpPerMessage": 0,
"XpPerOntimeHour": 0 "XpPerOntimeHour": 0,
"AFKChannelIds": []
} }
] ]
} }

View File

@ -18,6 +18,7 @@ class ServerSettings(ConfigurationModelABC):
self._max_voice_state_hours: int = 0 self._max_voice_state_hours: int = 0
self._xp_per_message: int = 0 self._xp_per_message: int = 0
self._xp_per_ontime_hour: int = 0 self._xp_per_ontime_hour: int = 0
self._afk_channel_ids: list[int] = []
@property @property
def id(self) -> str: def id(self) -> str:
@ -55,6 +56,10 @@ class ServerSettings(ConfigurationModelABC):
def xp_per_ontime_hour(self) -> int: def xp_per_ontime_hour(self) -> int:
return self._xp_per_ontime_hour return self._xp_per_ontime_hour
@property
def afk_channel_ids(self) -> list[int]:
return self._afk_channel_ids
def from_dict(self, settings: dict): def from_dict(self, settings: dict):
try: try:
self._id = int(settings['Id']) self._id = int(settings['Id'])
@ -66,6 +71,8 @@ class ServerSettings(ConfigurationModelABC):
self._max_voice_state_hours = int(settings['MaxVoiceStateHours']) self._max_voice_state_hours = int(settings['MaxVoiceStateHours'])
self._xp_per_message = int(settings['XpPerMessage']) self._xp_per_message = int(settings['XpPerMessage'])
self._xp_per_ontime_hour = int(settings['XpPerOntimeHour']) self._xp_per_ontime_hour = int(settings['XpPerOntimeHour'])
for id in settings['AFKChannelIds']:
self._afk_channel_ids.append(int(id))
except Exception as e: except Exception as e:
Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings') Console.error(f'[ ERROR ] [ {__name__} ]: Reading error in settings')
Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}') Console.error(f'[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}')

View File

@ -86,12 +86,12 @@ class User(TableABC):
UPDATE `Users` UPDATE `Users`
SET `XP` = {self._xp}, SET `XP` = {self._xp},
`LastModifiedAt` = '{self._modified_at}' `LastModifiedAt` = '{self._modified_at}'
WHERE `Id` = {self._user_id}; WHERE `UserId` = {self._user_id};
""") """)
@property @property
def delete_string(self) -> str: def delete_string(self) -> str:
return str(f""" return str(f"""
DELETE FROM `Users` DELETE FROM `Users`
WHERE `Id` = {self._user_id}; WHERE `UserId` = {self._user_id};
""") """)

View File

@ -81,9 +81,10 @@ class UserJoinedVoiceChannel(TableABC):
if self._leaved_on is not None: if self._leaved_on is not None:
return str(f""" return str(f"""
INSERT INTO `UserJoinedVoiceChannel` ( INSERT INTO `UserJoinedVoiceChannel` (
`UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt`
) VALUES ( ) VALUES (
{self._user.user_id}, {self._user.user_id},
{self._dc_channel_id},
'{self._joined_on}', '{self._joined_on}',
'{self._leaved_on}', '{self._leaved_on}',
'{self._created_at}', '{self._created_at}',
@ -93,9 +94,10 @@ class UserJoinedVoiceChannel(TableABC):
else: else:
return str(f""" return str(f"""
INSERT INTO `UserJoinedVoiceChannel` ( INSERT INTO `UserJoinedVoiceChannel` (
`UserId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` `UserId`, `DiscordChannelId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt`
) VALUES ( ) VALUES (
{self._user.user_id}, {self._user.user_id},
{self._dc_channel_id},
'{self._joined_on}', '{self._joined_on}',
'{self._created_at}', '{self._created_at}',
'{self._modified_at}' '{self._modified_at}'

View File

@ -14,10 +14,12 @@ from gismo_data.abc.known_user_repository_abc import KnownUserRepositoryABC
from gismo_data.abc.server_repository_abc import ServerRepositoryABC from gismo_data.abc.server_repository_abc import ServerRepositoryABC
from gismo_data.abc.user_joined_server_repository_abc import \ from gismo_data.abc.user_joined_server_repository_abc import \
UserJoinedServerRepositoryABC UserJoinedServerRepositoryABC
from gismo_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC
from gismo_data.abc.user_repository_abc import UserRepositoryABC from gismo_data.abc.user_repository_abc import UserRepositoryABC
from gismo_data.model.known_user import KnownUser from gismo_data.model.known_user import KnownUser
from gismo_data.model.user import User from gismo_data.model.user import User
from gismo_data.model.user_joined_server import UserJoinedServer from gismo_data.model.user_joined_server import UserJoinedServer
from gismo_data.model.user_joined_voice_channel import UserJoinedVoiceChannel
from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC from modules_core.abc.events.on_member_join_abc import OnMemberJoinABC
from modules_core.abc.events.on_member_remove_abc import OnMemberRemoveABC from modules_core.abc.events.on_member_remove_abc import OnMemberRemoveABC
from modules_core.abc.events.on_message_abc import OnMessageABC from modules_core.abc.events.on_message_abc import OnMessageABC
@ -37,6 +39,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS
known_users: KnownUserRepositoryABC, known_users: KnownUserRepositoryABC,
users: UserRepositoryABC, users: UserRepositoryABC,
user_joins: UserJoinedServerRepositoryABC, user_joins: UserJoinedServerRepositoryABC,
user_joins_vc: UserJoinedVoiceChannelRepositoryABC,
bot: BotServiceABC, bot: BotServiceABC,
db: DatabaseContextABC, db: DatabaseContextABC,
messenger: MessageServiceABC messenger: MessageServiceABC
@ -48,6 +51,7 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS
self._known_users = known_users self._known_users = known_users
self._users = users self._users = users
self._user_joins = user_joins self._user_joins = user_joins
self._user_joins_vc = user_joins_vc
self._bot = bot self._bot = bot
self._db = db self._db = db
self._messenger = messenger self._messenger = messenger
@ -128,6 +132,70 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS
except Exception as e: except Exception as e:
self._logger.error(__name__, f'Cannot get user {member.id}', e) self._logger.error(__name__, f'Cannot get user {member.id}', e)
def _update_voice_state(self, joined: bool, dc_user_id: int, dc_channel_id: int, srv_id: int):
user: User = None
try:
user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, srv_id)
except Exception as e:
self._logger.error(__name__, f'Cannot get user {dc_user_id}', e)
return
if user is None:
self._logger.error(__name__, f'User not found {dc_user_id}')
return
try:
if joined:
join = UserJoinedVoiceChannel(user, dc_channel_id, datetime.now())
self._user_joins_vc.add_user_joined_voice_channel(join)
self._db.save_changes()
return
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{user.server.discord_server_id}')
join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.user_id)
join.leaved_on = datetime.now()
# ontime as hours
ontime = (join.leaved_on - join.joined_on).total_seconds()/3600
old_xp = user.xp
user.xp += round(ontime * server_st.xp_per_ontime_hour)
self._user_joins_vc.update_user_joined_voice_channel(join)
self._users.update_user(user)
self._db.save_changes()
self._logger.debug(__name__, f'User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}')
except Exception as e:
self._logger.error(__name__, f'Ontime validation failed', e)
def _handle_message_for_xp(self, message: discord.Message):
dc_user_id = message.author.id
try:
server = self._servers.get_server_by_discord_id(message.guild.id)
except Exception as e:
self._logger.error(__name__, f'Cannot get server {message.guild.id}', e)
return
user: User = None
try:
user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id)
except Exception as e:
self._logger.error(__name__, f'Cannot get user {dc_user_id}', e)
return
if user is None:
self._logger.error(__name__, f'User not found {dc_user_id}')
return
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{user.server.discord_server_id}')
old_xp = user.xp
user.xp += server_st._xp_per_message
self._users.update_user(user)
self._db.save_changes()
self._logger.debug(__name__, f'User {user} sent message. xp: from {old_xp} to {user.xp}')
async def on_member_join(self, member: Union[discord.User, discord.Member]): async def on_member_join(self, member: Union[discord.User, discord.Member]):
self._logger.debug(__name__, f'Module {type(self)} started') self._logger.debug(__name__, f'Module {type(self)} started')
self._check_for_known_user(member) self._check_for_known_user(member)
@ -143,7 +211,40 @@ class Base(ModuleABC, OnMemberJoinABC, OnMemberRemoveABC, OnMessageABC, OnVoiceS
return return
self._apppend_received_message_count(message.guild.id) self._apppend_received_message_count(message.guild.id)
if not message.author.bot:
self._handle_message_for_xp(message)
async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState): async def on_voice_state_update(self, member: discord.Member, before: discord.VoiceState, after: discord.VoiceState):
self._logger.debug(__name__, f'Module {type(self)} started') self._logger.debug(__name__, f'Module {type(self)} started')
# todo: save ontime self._logger.trace(__name__, f'Detected on_voice_state_update {member.id} from {before} to {after}')
# todo: add xp to user when he goes offline u: discord.User = member
server_st: ServerSettings = self._config.get_configuration(f'DSERVER_{member.guild.id}')
server = self._servers.get_server_by_discord_id(member.guild.id)
try:
# join
if before.channel is None and after.channel is not None and after.channel.id not in server_st.afk_channel_ids:
self._logger.trace(__name__, f'User {u.id} joined {after.channel}')
self._update_voice_state(True, member.id, after.channel.id, server.server_id)
# leave
elif before.channel is not None and after.channel is None and before.channel.id not in server_st.afk_channel_ids:
self._logger.trace(__name__, f'User {u.id} left {before.channel}')
self._update_voice_state(False, member.id, before.channel.id, server.server_id)
# channel to channel
elif before.channel is not None and after.channel is not None:
# joined
if before.channel.id in server_st.afk_channel_ids and after.channel.id not in server_st.afk_channel_ids:
self._logger.trace(__name__, f'User {u.id} joined {after.channel}')
self._update_voice_state(True, member.id, after.channel.id, server.server_id)
# left
elif after.channel.id in server_st.afk_channel_ids and before.channel.id not in server_st.afk_channel_ids:
self._logger.trace(__name__, f'User {u.id} left {before.channel}')
self._update_voice_state(False, member.id, before.channel.id, server.server_id)
else:
self._logger.trace(__name__, f'User {u.id} switched to {after.channel}')
except Exception as e:
self._logger.error(__name__, f'Cannot handle voice state for user {u.id}', e)