A-0.3 - Basismodul #36
@ -26,7 +26,8 @@
|
|||||||
"GoodbyeMessage": "",
|
"GoodbyeMessage": "",
|
||||||
"MaxVoiceStateHours": 0,
|
"MaxVoiceStateHours": 0,
|
||||||
"XpPerMessage": 0,
|
"XpPerMessage": 0,
|
||||||
"XpPerOntimeHour": 0
|
"XpPerOntimeHour": 0,
|
||||||
|
"AFKChannelIds": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -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()}')
|
||||||
|
@ -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};
|
||||||
""")
|
""")
|
||||||
|
@ -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}'
|
||||||
|
@ -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)
|
||||||
|
Reference in New Issue
Block a user