0.3 - Statistiken (#46) #102

Merged
edraft merged 28 commits from #46 into 0.3 2022-11-09 20:55:06 +01:00
12 changed files with 382 additions and 1 deletions
Showing only changes of commit f24fd5e880 - Show all commits

View File

@ -195,7 +195,17 @@
}
},
"database": {},
"permission": {
"permission": {},
"stats": {
"list": {
"statistic": "Statistik",
"description": "Beschreibung"
},
"view": {
"statistic": "Statistik",
"description": "Beschreibung",
"failed": "Statistik kann nicht gezeigt werden :("
}
}
},
"api": {

View File

@ -0,0 +1 @@
# imports:

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,133 @@
from typing import List as TList
import discord
from cpl_discord.command import DiscordCommandABC
from cpl_query.extension import List
from cpl_translation import TranslatePipe
from discord import app_commands
from discord.ext import commands
from discord.ext.commands import Context
from bot_core.abc.client_utils_service_abc import ClientUtilsServiceABC
from bot_core.abc.message_service_abc import MessageServiceABC
from bot_core.logging.command_logger import CommandLogger
from bot_data.abc.server_repository_abc import ServerRepositoryABC
from modules.permission.abc.permission_service_abc import PermissionServiceABC
from modules.stats.model.statistic import Statistic
from modules.stats.service.statistic_service import StatisticService
from modules.stats.test.user_xp_asc import user_xp_asc
from modules.stats.test.user_xp_desc import user_xp_desc
class StatsGroup(DiscordCommandABC):
def __init__(
self,
logger: CommandLogger,
message_service: MessageServiceABC,
client_utils: ClientUtilsServiceABC,
translate: TranslatePipe,
permission_service: PermissionServiceABC,
statistic: StatisticService,
servers: ServerRepositoryABC,
):
DiscordCommandABC.__init__(self)
self._logger = logger
self._client_utils = client_utils
self._message_service = message_service
self._t = translate
self._permissions = permission_service
self._statistic = statistic
self._servers = servers
self._stats = List(Statistic, [
Statistic('Benutzer XP Aufsteigend', 'Zeigt XP von jedem Benutzer, aufsteigend nach XP', user_xp_asc),
Statistic('Benutzer XP Absteigend', 'Zeigt XP von jedem Benutzer, absteigend nach XP', user_xp_desc)
])
@commands.hybrid_group()
@commands.guild_only()
async def stats(self, ctx: Context):
pass
@stats.command(alias='rules')
@commands.guild_only()
async def list(self, ctx: Context, wait: int = None):
self._logger.debug(__name__, f'Received command stats list {ctx}')
if not await self._client_utils.check_if_bot_is_ready_yet_and_respond(ctx):
return
if not self._permissions.is_member_moderator(ctx.author):
await self._message_service.send_ctx_msg(ctx, self._t.transform('common.no_permission_message'))
self._logger.trace(__name__, f'Finished command stats list')
return
embed = discord.Embed(
title=self._t.transform('modules.auto_role.list.title'),
description=self._t.transform('modules.auto_role.list.description'),
color=int('ef9d0d', 16)
)
statistics = ''
descriptions = ''
for statistic in self._stats:
statistics += f'\n{statistic["Name"]}'
descriptions += f'\n{statistic["Description"]}'
embed.add_field(name=self._t.transform('modules.stats.list.statistic'), value=statistics, inline=True)
embed.add_field(name=self._t.transform('modules.stats.list.description'), value=statistics, inline=True)
await self._message_service.send_ctx_msg(ctx, embed, wait_before_delete=wait)
self._logger.trace(__name__, f'Finished command stats list')
@stats.command()
@commands.guild_only()
async def view(self, ctx: Context, name: str, wait: int = None):
self._logger.debug(__name__, f'Received command stats {ctx}:{name}')
if not await self._client_utils.check_if_bot_is_ready_yet_and_respond(ctx):
edraft marked this conversation as resolved Outdated

Hier wurde zwei mal value=statisticsangegeben

embed.add_field(name=self._t.transform('modules.stats.list.statistic'), value=statistics, inline=True)
embed.add_field(name=self._t.transform('modules.stats.list.description'), value=statistics, inline=True)

statt

embed.add_field(name=self._t.transform('modules.stats.list.statistic'), value=statistics, inline=True)
embed.add_field(name=self._t.transform('modules.stats.list.description'), value=descriptions, inline=True)
Hier wurde zwei mal ```value=statistics```angegeben ```python embed.add_field(name=self._t.transform('modules.stats.list.statistic'), value=statistics, inline=True) embed.add_field(name=self._t.transform('modules.stats.list.description'), value=statistics, inline=True) ``` statt ```python embed.add_field(name=self._t.transform('modules.stats.list.statistic'), value=statistics, inline=True) embed.add_field(name=self._t.transform('modules.stats.list.description'), value=descriptions, inline=True) ```
return
if ctx.guild is None:
return
try:
server = self._servers.get_server_by_discord_id(ctx.guild.id)
statistic = self._stats.where(lambda s: s.name == name).single()
result = await self._statistic.execute(statistic.func, server)
edraft marked this conversation as resolved
Review

Fehlt hier nicht noch ein Permission check?

if not self._permissions.is_member_moderator(ctx.author):
    await self._message_service.send_ctx_msg(ctx, self._t.transform('common.no_permission_message'))
    self._logger.trace(__name__, f'Finished command stats list')
    return
Fehlt hier nicht noch ein Permission check? ```python if not self._permissions.is_member_moderator(ctx.author): await self._message_service.send_ctx_msg(ctx, self._t.transform('common.no_permission_message')) self._logger.trace(__name__, f'Finished command stats list') return ```
# headers = ''
# rows = ''
# for header in result.header:
# headers += f'\n{header}'
#
# for row in result.values:
# row_str = ''
# for column in row:
# row_str += f'\n{column}'
# rows += f'\n{row_str}'
embed = discord.Embed(
title=statistic.name,
description=statistic.description,
color=int('ef9d0d', 16)
)
for i in range(result.header.count()):
header = result.header[i]
value = ''
for row in result.values:
value += f'\n{row[i]}'
embed.add_field(name=header, value=value, inline=True)
# embed.add_field(name=self._t.transform('modules.auto_role.list.message_id'), value=rows, inline=True)
await self._message_service.send_ctx_msg(ctx, embed, wait_before_delete=wait)
# await self._message_service.send_ctx_msg(ctx, name, wait_before_delete=wait)
except Exception as e:
self._logger.error(__name__, f'Cannot view statistic {name}', e)
await self._message_service.send_ctx_msg(ctx, self._t.transform('modules.stats.view.failed'))
self._logger.trace(__name__, f'Finished stats command')
@view.autocomplete('name')
async def view_autocomplete(self, interaction: discord.Interaction, current: str) -> TList[app_commands.Choice[str]]:
return [app_commands.Choice(name=f'{statistic.name}: {statistic.description}', value=statistic.name) for statistic in self._stats]

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,21 @@
from typing import Callable
class Statistic:
def __init__(self, name: str, description: str, func: Callable):
self._name = name
self._description = description
self._func = func
@property
def name(self) -> str:
return self._name
@property
def description(self) -> str:
return self._description
@property
def func(self) -> Callable:
return self._func

View File

@ -0,0 +1,24 @@
from cpl_query.extension import List
class StatisticResult:
def __init__(self):
self._header = List(str)
self._values = List(List)
@property
def header(self) -> List[str]:
return self._header
@header.setter
def header(self, value: List[str]):
self._header = value
@property
def values(self) -> List[List]:
return self._values
@values.setter
def values(self, value: List[List]):
self._values = value

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,69 @@
from abc import abstractmethod
from typing import Callable
from cpl_discord.service import DiscordBotServiceABC
from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC
from bot_data.abc.client_repository_abc import ClientRepositoryABC
from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC
from bot_data.abc.level_repository_abc import LevelRepositoryABC
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 bot_data.model.server import Server
from modules.stats.model.statistic_result import StatisticResult
class StatisticService:
def __init__(
self,
auto_roles: AutoRoleRepositoryABC,
clients: ClientRepositoryABC,
known_users: KnownUserRepositoryABC,
levels: LevelRepositoryABC,
servers: ServerRepositoryABC,
user_joined_servers: UserJoinedServerRepositoryABC,
user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC,
users: UserRepositoryABC,
bot: DiscordBotServiceABC,
):
self._auto_roles = auto_roles
self._clients = clients
self._known_users = known_users
self._levels = levels
self._servers = servers
self._user_joined_servers = user_joined_servers
self._user_joined_voice_channel = user_joined_voice_channel
self._users = users
self._bot = bot
async def execute(self, _f: Callable, server: Server) -> StatisticResult:
guild = self._bot.guilds.where(lambda g: g.id == server.discord_server_id).single()
return await _f(
self._auto_roles
.get_auto_roles()
.where(lambda x: x.server.server_id == server.server_id),
self._clients
.get_clients()
.where(lambda x: x.server.server_id == server.server_id),
self._known_users.get_users(),
self._levels
.get_levels()
.where(lambda x: x.server.server_id == server.server_id),
self._servers
.get_servers()
.where(lambda x: x.server_id == server.server_id),
self._user_joined_servers
.get_user_joined_servers()
.where(lambda x: x.user.server.server_id == server.server_id),
edraft marked this conversation as resolved
Review

Ich merke hier mal an dass self._known_users.get_users() kein Lamdaausdruck hat wie die anderen Parametern. Sollte dies hier nicht gebraucht werden, dann dieser Thread resolved werden.

Ich merke hier mal an dass ```self._known_users.get_users()``` kein Lamdaausdruck hat wie die anderen Parametern. Sollte dies hier nicht gebraucht werden, dann dieser Thread resolved werden.
Review

KnownUsers ist ne Liste aller bekannten discord.Member

KnownUsers ist ne Liste aller bekannten discord.Member
self._user_joined_voice_channel
.get_user_joined_voice_channels()
.where(lambda x: x.user.server.server_id == server.server_id),
self._users
.get_users()
.where(lambda x: x.server.server_id == server.server_id),
guild
)

View File

@ -0,0 +1,46 @@
{
"ProjectSettings": {
"Name": "stats",
"Version": {
"Major": "0",
"Minor": "0",
"Micro": "0"
},
"Author": "",
"AuthorEmail": "",
"Description": "",
"LongDescription": "",
"URL": "",
"CopyrightDate": "",
"CopyrightName": "",
"LicenseName": "",
"LicenseDescription": "",
"Dependencies": [
"cpl-core>=2022.10.0.post7"
],
"DevDependencies": [
"cpl-cli>=2022.10.1"
],
"PythonVersion": ">=3.10.4",
"PythonPath": {
"linux": ""
},
"Classifiers": []
},
"BuildSettings": {
"ProjectType": "library",
"SourcePath": "",
"OutputPath": "../../dist",
"Main": "stats.main",
"EntryPoint": "stats",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

@ -0,0 +1,37 @@
from cpl_discord.container import Guild
from cpl_query.extension import List
from bot_data.model.auto_role import AutoRole
from bot_data.model.client import Client
from bot_data.model.known_user import KnownUser
from bot_data.model.level import Level
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 modules.stats.model.statistic_result import StatisticResult
async def user_xp_asc(
auto_roles: List[AutoRole],
clients: List[Client],
known_users: List[KnownUser],
levels: List[Level],
servers: List[Server],
user_joined_servers: List[UserJoinedServer],
user_joined_voice_channel: List[UserJoinedVoiceChannel],
users: List[User],
guild: Guild
) -> StatisticResult:
result = StatisticResult()
result.header.append('Name')
result.header.append('XP')
for user in users.order_by(lambda u: u.xp):
row = List(str)
member = guild.get_member(user.discord_id)
row.append(member.name)
row.append(str(user.xp))
result.values.append(row)
return result

View File

@ -0,0 +1,37 @@
from cpl_discord.container import Guild
from cpl_query.extension import List
from bot_data.model.auto_role import AutoRole
from bot_data.model.client import Client
from bot_data.model.known_user import KnownUser
from bot_data.model.level import Level
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 modules.stats.model.statistic_result import StatisticResult
async def user_xp_desc(
auto_roles: List[AutoRole],
clients: List[Client],
known_users: List[KnownUser],
levels: List[Level],
servers: List[Server],
user_joined_servers: List[UserJoinedServer],
user_joined_voice_channel: List[UserJoinedVoiceChannel],
users: List[User],
guild: Guild
) -> StatisticResult:
result = StatisticResult()
result.header.append('Name')
result.header.append('XP')
for user in users.order_by_descending(lambda u: u.xp):
row = List(str)
member = guild.get_member(user.discord_id)
row.append(member.name)
row.append(str(user.xp))
result.values.append(row)
return result