Added logic to handle level by xp #25

This commit is contained in:
Sven Heidemann 2022-11-06 21:34:58 +01:00
parent 8aee72856c
commit 164671a07c
9 changed files with 138 additions and 34 deletions

View File

@ -63,7 +63,7 @@ class LevelRepositoryService(LevelRepositoryABC):
def get_levels_by_server_id(self, server_id: int) -> List[Level]:
levels = List(Level)
self._logger.trace(__name__, f'Send SQL command: {Level.get_select_by_server_id_string(server_id)}')
results = self._context.select(Level.get_select_by_server_id_string(server_id))[0]
results = self._context.select(Level.get_select_by_server_id_string(server_id))
for result in results:
self._logger.trace(__name__, f'Get level with id {result[0]}')

View File

@ -13,14 +13,20 @@ class LevelSettings(ConfigurationModelABC):
ConfigurationModelABC.__init__(self)
self._levels = List(Level)
self._level_header = ''
@property
def levels(self) -> List[Level]:
return self._levels
@property
def level_header(self) -> str:
return self._level_header
def from_dict(self, settings: dict):
try:
for level in settings:
self._level_header = settings['LevelHeader']
for level in settings['Levels']:
self._levels.append(Level(
level['Name'],
level['Color'],

View File

@ -1,28 +1,31 @@
{
"Level": [
{
"Name": "Newbie",
"Color": "0x1abc9c",
"MinXp": 0,
"Permissions": 968552209984
},
{
"Name": "Keks",
"Color": "0x2ecc71",
"MinXp": 100,
"Permissions": 1002928856640
},
{
"Name": "Doppelkeks",
"Color": "0x3498db",
"MinXp": 200,
"Permissions": 1071849660224
},
{
"Name": "Auror",
"Color": "0xf1c40f",
"MinXp": 300,
"Permissions": 1089042120513
}
]
"Level": {
"LevelHeader": "~~~ Level ~~~",
"Levels": [
{
"Name": "Newbie",
"Color": "0x1abc9c",
"MinXp": 0,
"Permissions": 968552209984
},
{
"Name": "Keks",
"Color": "0x2ecc71",
"MinXp": 100,
"Permissions": 1002928856640
},
{
"Name": "Doppelkeks",
"Color": "0x3498db",
"MinXp": 200,
"Permissions": 1071849660224
},
{
"Name": "Auror",
"Color": "0xf1c40f",
"MinXp": 300,
"Permissions": 1089042120513
}
]
}
}

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
"""
bot Keksdose bot
~~~~~~~~~~~~~~~~~~~
Discord bot for the Keksdose discord Server
:copyright: (c) 2022 sh-edraft.de
:license: MIT, see LICENSE for more details.
"""
__title__ = 'modules.base.events'
__author__ = 'Sven Heidemann'
__license__ = 'MIT'
__copyright__ = 'Copyright (c) 2022 sh-edraft.de'
__version__ = '0.3.dev70'
from collections import namedtuple
# imports:
VersionInfo = namedtuple('VersionInfo', 'major minor micro')
version_info = VersionInfo(major='0', minor='3', micro='dev70')

View File

@ -0,0 +1,21 @@
import discord
from cpl_discord.events import OnMessageABC
from bot_core.logging.message_logger import MessageLogger
from modules.level.service.level_service import LevelService
class LevelOnMessageEvent(OnMessageABC):
def __init__(
self,
logger: MessageLogger,
level: LevelService
):
OnMessageABC.__init__(self)
self._logger = logger
self._level = level
async def on_message(self, message: discord.Message):
self._logger.debug(__name__, f'Module {type(self)} started')
await self._level.check_level(message.author)

View File

@ -0,0 +1,23 @@
import discord
from cpl_core.logging import LoggerABC
from cpl_discord.events import OnVoiceStateUpdateABC
from modules.level.service.level_service import LevelService
class LevelOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC):
def __init__(
self,
logger: LoggerABC,
level: LevelService
):
OnVoiceStateUpdateABC.__init__(self)
self._logger = logger
self._level = level
self._logger.info(__name__, f'Module {type(self)} loaded')
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')
await self._level.check_level(member)

View File

@ -3,10 +3,13 @@ import os
from cpl_core.configuration import ConfigurationABC
from cpl_core.dependency_injection import ServiceCollectionABC
from cpl_core.environment import ApplicationEnvironmentABC
from cpl_discord.discord_event_types_enum import DiscordEventTypesEnum
from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
from bot_core.abc.module_abc import ModuleABC
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
from modules.level.events.level_on_message_event import LevelOnMessageEvent
from modules.level.events.level_on_voice_state_update_event import LevelOnVoiceStateUpdateEvent
from modules.level.level_seeder import LevelSeeder
from modules.level.service.level_service import LevelService
@ -25,3 +28,6 @@ class LevelModule(ModuleABC):
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
services.add_transient(LevelSeeder)
services.add_transient(LevelService)
self._dc.add_event(DiscordEventTypesEnum.on_message.value, LevelOnMessageEvent)
self._dc.add_event(DiscordEventTypesEnum.on_voice_state_update.value, LevelOnVoiceStateUpdateEvent)

View File

@ -18,14 +18,16 @@ class LevelSeeder(DataSeederABC):
DataSeederABC.__init__(self)
self._logger = logger
self._default_levels = levels.levels.order_by_descending(lambda l: l.min_xp)
self._levels = level_repo
self._servers = servers
self._bot = bot
self._level_header = levels.level_header
self._default_levels = levels.levels.order_by_descending(lambda l: l.min_xp)
async def _create_level(self, level: Level, guild: Guild, server: Server):
try:
if guild.roles.where(lambda r: r.name == level.name).count() > 0:
if guild.roles.where(lambda r: r.name == level.name).first_or_default() is not None:
return
await guild.create_role(name=level.name, colour=Colour(int(level.color, 16)), hoist=False, mentionable=True, permissions=Permissions(level.permissions))
@ -39,8 +41,8 @@ class LevelSeeder(DataSeederABC):
# create levels
for guild in self._bot.guilds:
created_default = False
if guild.roles.where(lambda r: r.name == '___ Level ___').count() == 0:
await guild.create_role(name='___ Level ___')
if guild.roles.where(lambda r: r.name == self._level_header).first_or_default() is None:
await guild.create_role(name=self._level_header)
server = self._servers.find_server_by_discord_id(guild.id)
if server is None:
@ -64,7 +66,7 @@ class LevelSeeder(DataSeederABC):
if created_default:
continue
position_above_levels = guild.roles.where(lambda r: r.name == '~~~ Level ~~~').single().position
position_above_levels = guild.roles.where(lambda r: r.name == self._level_header).single().position
for role in guild.roles.order_by_descending(lambda r: r.position):
if levels.where(lambda l: l.name == role.name).count() == 0:
continue

View File

@ -1,3 +1,4 @@
import discord
from cpl_core.database.context import DatabaseContextABC
from cpl_core.logging import LoggerABC
from cpl_discord.container import Guild, Role, Member
@ -6,6 +7,7 @@ from cpl_discord.service import DiscordBotServiceABC
from bot_data.model.level import Level
from bot_data.model.user import User
from bot_data.service.level_repository_service import LevelRepositoryService
from bot_data.service.server_repository_service import ServerRepositoryService
from bot_data.service.user_repository_service import UserRepositoryService
@ -17,17 +19,19 @@ class LevelService:
db: DatabaseContextABC,
levels: LevelRepositoryService,
users: UserRepositoryService,
servers: ServerRepositoryService,
bot: DiscordBotServiceABC
):
self._logger = logger
self._db = db
self._levels = levels
self._users = users
self._servers = servers
self._bot = bot
def get_level(self, user: User) -> Level:
levels = self._levels.get_levels_by_server_id(user.server.server_id).order_by(lambda l: l.min_xp)
return levels.where(lambda l: l.min_xp > user.xp).first()
return levels.where(lambda l: user.xp >= l.min_xp).first()
async def set_level(self, user: User):
level_names = self._levels.get_levels_by_server_id(user.server.server_id).select(lambda l: l.name)
@ -45,9 +49,22 @@ class LevelService:
except Exception as e:
self._logger.error(__name__, f'Removing role {role.name} from {member.name} failed!', e)
if level_role in member.roles:
return
try:
self._logger.debug(__name__, f'Try to add role {level_role.name} to {member.name}')
await member.add_roles(level_role)
self._logger.info(__name__, f'Add role {level_role.name} to {member.name}')
except Exception as e:
self._logger.error(__name__, f'Adding role {level_role.name} to {member.name} failed!', e)
async def check_level(self, member: discord.Member):
if member.bot:
return
server = self._servers.get_server_by_discord_id(member.guild.id)
user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id)
if user is None:
self._logger.warn(__name__, f'User not found {member.guild.name}@{member.name}')
await self.set_level(user)