Added user set command #22 #143
@ -161,25 +161,36 @@
|
||||
"max_char_count_exceeded": "Der Text darf nicht mehr als 128 Zeichen lang sein!"
|
||||
},
|
||||
"user": {
|
||||
"atr": {
|
||||
"id": "Id",
|
||||
"name": "Name",
|
||||
"discord_join": "Discord beigetreten am",
|
||||
"last_join": "Server beigetreten am",
|
||||
"xp": "XP",
|
||||
"ontime": "Ontime",
|
||||
"roles": "Rollen",
|
||||
"joins": "Beitritte",
|
||||
"lefts": "Abgänge",
|
||||
"warnings": "Verwarnungen"
|
||||
},
|
||||
"info": {
|
||||
"fields": {
|
||||
"id": "Id",
|
||||
"name": "Name",
|
||||
"discord_join": "Discord beigetreten am",
|
||||
"last_join": "Server beigetreten am",
|
||||
"xp": "XP",
|
||||
"ontime": "Ontime",
|
||||
"roles": "Rollen",
|
||||
"joins": "Beitritte",
|
||||
"lefts": "Abgänge",
|
||||
"warnings": "Verwarnungen"
|
||||
},
|
||||
"footer": ""
|
||||
},
|
||||
"get": {
|
||||
"atr_not_found": "Das Attribut {} konnte nicht gefunden werden :(",
|
||||
"xp": "{} hat {} xp",
|
||||
"ontime": "{} war insgesamt {} Stunden aktiv in einem Sprachkanal"
|
||||
},
|
||||
"set": {
|
||||
"xp": "{} hat nun {} xp",
|
||||
"error": {
|
||||
"value_type_not_numeric": "Der angegebende Wert ist keine Ganzzahl! :(",
|
||||
"type_error": "Der angegebene Wert konnte nicht als eine Ganzzahl interpretiert werden :(",
|
||||
"database_error": "Beim Speichern des Wertes kam es zu einem Fehler :(",
|
||||
"general_error": "Bei der Ausführung dieses Befehls kam es zu einen Fehler :("
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"atr_not_found": "Das Attribut {} konnte nicht gefunden werden :("
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2,12 +2,14 @@ from typing import Optional, List
|
||||
|
||||
import discord
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.command import DiscordCommandABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
from cpl_translation import TranslatePipe
|
||||
from discord import app_commands
|
||||
from discord.ext import commands
|
||||
from discord.ext.commands import Context
|
||||
from mysql.connector.errors import DatabaseError
|
||||
|
||||
from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC
|
||||
from bot_core.abc.message_service_abc import MessageServiceABC
|
||||
@ -18,6 +20,7 @@ from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC
|
||||
from bot_data.abc.user_joined_voice_channel_abc import UserJoinedVoiceChannelRepositoryABC
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from modules.level.service.level_service import LevelService
|
||||
from modules.permission.abc.permission_service_abc import PermissionServiceABC
|
||||
|
||||
|
||||
@ -32,11 +35,13 @@ class UserGroup(DiscordCommandABC):
|
||||
client_utils: ClientUtilsServiceABC,
|
||||
permissions: PermissionServiceABC,
|
||||
servers: ServerRepositoryABC,
|
||||
db: DatabaseContextABC,
|
||||
users: UserRepositoryABC,
|
||||
user_joined_servers: UserJoinedServerRepositoryABC,
|
||||
user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC,
|
||||
translate: TranslatePipe,
|
||||
date: DateTimeOffsetPipe
|
||||
date: DateTimeOffsetPipe,
|
||||
level: LevelService
|
||||
):
|
||||
DiscordCommandABC.__init__(self)
|
||||
|
||||
@ -47,14 +52,21 @@ class UserGroup(DiscordCommandABC):
|
||||
self._client_utils = client_utils
|
||||
self._permissions = permissions
|
||||
self._servers = servers
|
||||
self._db = db
|
||||
self._users = users
|
||||
self._user_joined_servers = user_joined_servers
|
||||
self._user_joined_voice_channel = user_joined_voice_channel
|
||||
self._t = translate
|
||||
self._date = date
|
||||
self._level = level
|
||||
|
||||
self._logger.trace(__name__, f'Loaded command service: {type(self).__name__}')
|
||||
|
||||
self._atr_dict = {
|
||||
"xp": self._t.transform('modules.base.user.atr.xp'),
|
||||
'ontime': self._t.transform('modules.base.user.atr.ontime')
|
||||
}
|
||||
|
||||
@commands.hybrid_group()
|
||||
@commands.guild_only()
|
||||
async def user(self, ctx: Context):
|
||||
@ -87,25 +99,25 @@ class UserGroup(DiscordCommandABC):
|
||||
ontime = self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id).sum(
|
||||
lambda join: round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2))
|
||||
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.id'), value=member.id)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.name'), value=member.name)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.discord_join'),
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.id'), value=member.id)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.name'), value=member.name)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.discord_join'),
|
||||
value=self._date.transform(member.created_at), inline=False)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.last_join'),
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.last_join'),
|
||||
value=self._date.transform(member.joined_at), inline=False)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.xp'), value=str(user.xp))
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.ontime'), value=str(ontime))
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.xp'), value=str(user.xp))
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.ontime'), value=str(ontime))
|
||||
|
||||
roles = ''
|
||||
for role in member.roles:
|
||||
roles += f'{role.name}\n'
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.roles'), value=roles, inline=False)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.roles'), value=roles, inline=False)
|
||||
|
||||
if is_mod or member == ctx.author:
|
||||
joins_string = ''
|
||||
for join in joins:
|
||||
joins_string += f'{self._date.transform(join.joined_on)}\n'
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.joins'), value=joins_string)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.joins'), value=joins_string)
|
||||
|
||||
if is_mod or member == ctx.author:
|
||||
lefts_string = ''
|
||||
@ -116,10 +128,10 @@ class UserGroup(DiscordCommandABC):
|
||||
continue
|
||||
lefts_string += f'{self._date.transform(join.leaved_on)}\n'
|
||||
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.lefts'), value=lefts_string)
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.lefts'), value=lefts_string)
|
||||
|
||||
if is_mod or member == ctx.author:
|
||||
embed.add_field(name=self._t.transform('modules.base.user.info.fields.warnings'),
|
||||
embed.add_field(name=self._t.transform('modules.base.user.atr.warnings'),
|
||||
value=self._t.transform('common.not_implemented_yet'), inline=False)
|
||||
|
||||
# send to interaction because of sensitive data
|
||||
@ -130,7 +142,7 @@ class UserGroup(DiscordCommandABC):
|
||||
@commands.guild_only()
|
||||
@CommandChecks.check_is_ready()
|
||||
async def get(self, ctx: Context, atr: str, member: discord.Member = None):
|
||||
self._logger.debug(__name__, f'Received command user-info {ctx}:{member}')
|
||||
self._logger.debug(__name__, f'Received command user-get {ctx}:{member}')
|
||||
|
||||
is_mod = self._permissions.is_member_moderator(ctx.author)
|
||||
if member is not None and not is_mod:
|
||||
@ -143,20 +155,19 @@ class UserGroup(DiscordCommandABC):
|
||||
server = self._servers.find_server_by_discord_id(ctx.guild.id)
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id)
|
||||
|
||||
match atr:
|
||||
case 'xp':
|
||||
value = str(user.xp)
|
||||
|
||||
case 'ontime':
|
||||
value = str(round(
|
||||
self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id)
|
||||
.sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600),
|
||||
2
|
||||
))
|
||||
if atr == self._atr_dict["xp"]:
|
||||
value = str(user.xp)
|
||||
|
||||
case other:
|
||||
await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.base.user.get.atr_not_found').format(atr))
|
||||
return
|
||||
elif atr == self._atr_dict["ontime"]:
|
||||
value = str(round(
|
||||
Ebola-Chan marked this conversation as resolved
Outdated
|
||||
self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id)
|
||||
.sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600),
|
||||
2
|
||||
))
|
||||
|
||||
else:
|
||||
await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform('modules.base.user.error.atr_not_found').format(atr))
|
||||
return
|
||||
|
||||
await self._message_service.send_interaction_msg(
|
||||
ctx.interaction,
|
||||
@ -165,5 +176,51 @@ class UserGroup(DiscordCommandABC):
|
||||
|
||||
@get.autocomplete('atr')
|
||||
async def get_autocomplete(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]:
|
||||
atr_list = ['xp', 'ontime']
|
||||
atr_list = [self._atr_dict["xp"], self._atr_dict["ontime"]]
|
||||
return [app_commands.Choice(name=atr, value=atr) for atr in atr_list]
|
||||
|
||||
@user.command()
|
||||
@commands.guild_only()
|
||||
@CommandChecks.check_is_ready()
|
||||
@CommandChecks.check_is_member_moderator()
|
||||
async def set(self, ctx: Context, atr: str, value: str, member: discord.Member = None):
|
||||
self._logger.debug(__name__, f'Received command user-set {ctx}:{member}')
|
||||
|
||||
if member is None or not isinstance(member, discord.Member):
|
||||
member = ctx.author
|
||||
|
||||
server = self._servers.find_server_by_discord_id(ctx.guild.id)
|
||||
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id)
|
||||
|
||||
if atr == self._atr_dict["xp"]:
|
||||
if not value.isnumeric():
|
||||
await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform(
|
||||
'modules.base.user.set.error.value_type_not_numeric'))
|
||||
return
|
||||
|
||||
try:
|
||||
user.xp = int(value)
|
||||
Ebola-Chan marked this conversation as resolved
Outdated
edraft
commented
Relativ ungenau. Entweder änderst du die beschreibung von dem error oder du machst zwei try except blöcke, einmal für den type cast und dann für die manipulation des users inkl. level check Relativ ungenau. Entweder änderst du die beschreibung von dem error oder du machst zwei try except blöcke, einmal für den type cast und dann für die manipulation des users inkl. level check
Ebola-Chan
commented
Das Exceptionhandling für das "check_level" würde ich lieber dann in der Methode selber machen und das in einem separaten Issue, da ich dafür weitere Exceptionklassen erstellen möchte, um Exceptions in der Methode besser von den allgemeinen Databaseexceptions zu differenzieren. Das Exceptionhandling für das "check_level" würde ich lieber dann in der Methode selber machen und das in einem separaten Issue, da ich dafür weitere Exceptionklassen erstellen möchte, um Exceptions in der Methode besser von den allgemeinen Databaseexceptions zu differenzieren.
|
||||
except TypeError as te:
|
||||
self._logger.error(__name__, f'String value couldn\'t be converted to int', te)
|
||||
await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform(
|
||||
'modules.base.user.set.error.type_error'))
|
||||
return
|
||||
else:
|
||||
self._users.update_user(user)
|
||||
self._db.save_changes()
|
||||
await self._level.check_level(member)
|
||||
|
||||
else:
|
||||
await self._message_service.send_interaction_msg(ctx.interaction, self._t.transform(
|
||||
Ebola-Chan marked this conversation as resolved
Outdated
edraft
commented
Der ist bei weitem unnötig xD Des Weiteren ist DatabaseError um das update_user abzufangen ungenau bzw als solches auch nicht ötig. Der ist bei weitem unnötig xD
Wenn wir mal in check_level reinschauen sehen wir, dass dort alle Fehler abefangen werden.
Des Weiteren ist DatabaseError um das update_user abzufangen ungenau bzw als solches auch nicht ötig.
Ebola-Chan
commented
Errorhandling entfernt. Nur TypeError wird behandelt. Errorhandling entfernt. Nur TypeError wird behandelt.
|
||||
'modules.base.user.error.atr_not_found').format(atr))
|
||||
return
|
||||
|
||||
await self._message_service.send_interaction_msg(
|
||||
Ebola-Chan marked this conversation as resolved
edraft
commented
Es wäre ne idee, dass diese strings irgendwie aus translation oder config kommen. Also das man da halt ne liste von diesen Strings hat. Ist auch diesen drei Befehlen immer der Fall Es wäre ne idee, dass diese strings irgendwie aus translation oder config kommen. Also das man da halt ne liste von diesen Strings hat. Ist auch diesen drei Befehlen immer der Fall
|
||||
ctx.interaction,
|
||||
Ebola-Chan marked this conversation as resolved
Outdated
edraft
commented
DieseBlock ist wegen command error handling an und für auch nicht nötig. Hier könnte man wenn man wollte die Datenbankfehler abfangen DieseBlock ist wegen command error handling an und für auch nicht nötig. Hier könnte man wenn man wollte die Datenbankfehler abfangen
|
||||
self._t.transform(f'modules.base.user.set.{atr}').format(member.mention, value)
|
||||
)
|
||||
|
||||
@set.autocomplete('atr')
|
||||
async def set_autocomplete(self, interaction: discord.Interaction, current: str) -> List[app_commands.Choice[str]]:
|
||||
atr_list = [self._atr_dict["xp"]]
|
||||
return [app_commands.Choice(name=atr, value=atr) for atr in atr_list]
|
||||
|
Mach das bitte mit nem elif und als dict in der Klasse und keine weitere Klasse dafür einführen
https://stackoverflow.com/questions/72638083/python-match-case-dictionary-keys
Match-Case-Statement gegen If-Else-Statement getauscht