Improved achievement logic #268_achievements
This commit is contained in:
parent
2578c47c44
commit
e36f0b8c76
@ -7,6 +7,7 @@
|
|||||||
"bot-core": "src/bot_core/bot-core.json",
|
"bot-core": "src/bot_core/bot-core.json",
|
||||||
"bot-data": "src/bot_data/bot-data.json",
|
"bot-data": "src/bot_data/bot-data.json",
|
||||||
"bot-graphql": "src/bot_graphql/bot-graphql.json",
|
"bot-graphql": "src/bot_graphql/bot-graphql.json",
|
||||||
|
"achievements": "src/modules/achievements/achievements.json",
|
||||||
"auto-role": "src/modules/auto_role/auto-role.json",
|
"auto-role": "src/modules/auto_role/auto-role.json",
|
||||||
"base": "src/modules/base/base.json",
|
"base": "src/modules/base/base.json",
|
||||||
"boot-log": "src/modules/boot_log/boot-log.json",
|
"boot-log": "src/modules/boot_log/boot-log.json",
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit e1c1efac984a04826c0c2713a26129b9d34b21d6
|
Subproject commit 35c9d4ecb4102b1b4ce758221d1efda25672e7e0
|
@ -11,7 +11,6 @@ from bot_core.configuration.bot_logging_settings import BotLoggingSettings
|
|||||||
from bot_core.configuration.bot_settings import BotSettings
|
from bot_core.configuration.bot_settings import BotSettings
|
||||||
from modules.base.configuration.base_settings import BaseSettings
|
from modules.base.configuration.base_settings import BaseSettings
|
||||||
from modules.boot_log.configuration.boot_log_settings import BootLogSettings
|
from modules.boot_log.configuration.boot_log_settings import BootLogSettings
|
||||||
from modules.level.configuration.level_settings import LevelSettings
|
|
||||||
from modules.permission.configuration.permission_settings import PermissionSettings
|
from modules.permission.configuration.permission_settings import PermissionSettings
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +36,6 @@ class StartupSettingsExtension(StartupExtensionABC):
|
|||||||
self._configure_settings_with_sub_settings(configuration, BotSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(configuration, BotSettings, lambda x: x.servers, lambda x: x.id)
|
||||||
self._configure_settings_with_sub_settings(configuration, BaseSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(configuration, BaseSettings, lambda x: x.servers, lambda x: x.id)
|
||||||
self._configure_settings_with_sub_settings(configuration, BootLogSettings, lambda x: x.servers, lambda x: x.id)
|
self._configure_settings_with_sub_settings(configuration, BootLogSettings, lambda x: x.servers, lambda x: x.id)
|
||||||
self._configure_settings_with_sub_settings(configuration, LevelSettings, lambda x: x.servers, lambda x: x.id)
|
|
||||||
self._configure_settings_with_sub_settings(
|
self._configure_settings_with_sub_settings(
|
||||||
configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id
|
configuration, PermissionSettings, lambda x: x.servers, lambda x: x.id
|
||||||
)
|
)
|
||||||
@ -50,9 +48,9 @@ class StartupSettingsExtension(StartupExtensionABC):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _configure_settings_with_sub_settings(
|
def _configure_settings_with_sub_settings(
|
||||||
config: ConfigurationABC, settings: Type, list_atr: Callable, atr: Callable
|
config: ConfigurationABC, settings_type: Type, list_atr: Callable, atr: Callable
|
||||||
):
|
):
|
||||||
settings: Optional[settings] = config.get_configuration(settings)
|
settings: Optional[settings_type] = config.get_configuration(settings_type)
|
||||||
if settings is None:
|
if settings is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -93,6 +93,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"modules": {
|
"modules": {
|
||||||
|
"achievements": {
|
||||||
|
"got_new_achievement": "{} hat die Errungenschaft {} freigeschaltet :D"
|
||||||
|
},
|
||||||
"auto_role": {
|
"auto_role": {
|
||||||
"add": {
|
"add": {
|
||||||
"error": {
|
"error": {
|
||||||
|
@ -1,21 +1,30 @@
|
|||||||
import traceback
|
|
||||||
|
|
||||||
from cpl_core.configuration import ConfigurationModelABC
|
from cpl_core.configuration import ConfigurationModelABC
|
||||||
from cpl_core.console import Console
|
|
||||||
from cpl_query.extension import List
|
from cpl_query.extension import List
|
||||||
|
|
||||||
|
from bot_api.json_processor import JSONProcessor
|
||||||
from bot_core.configuration.server_settings import ServerSettings
|
from bot_core.configuration.server_settings import ServerSettings
|
||||||
|
|
||||||
|
|
||||||
class BotSettings(ConfigurationModelABC):
|
class BotSettings(ConfigurationModelABC):
|
||||||
def __init__(self):
|
def __init__(
|
||||||
|
self,
|
||||||
|
technicians: list = None,
|
||||||
|
wait_for_restart: int = 2,
|
||||||
|
wait_for_shutdown: int = 2,
|
||||||
|
cache_max_messages: int = 1000,
|
||||||
|
server_settings: dict = None,
|
||||||
|
):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
|
self._technicians: List[int] = List(int) if technicians is None else technicians
|
||||||
|
self._wait_for_restart = wait_for_restart
|
||||||
|
self._wait_for_shutdown = wait_for_shutdown
|
||||||
|
self._cache_max_messages = cache_max_messages
|
||||||
|
|
||||||
self._servers: List[ServerSettings] = List(ServerSettings)
|
self._servers: List[ServerSettings] = List(ServerSettings)
|
||||||
self._technicians: List[int] = List(int)
|
|
||||||
self._wait_for_restart = 2
|
if server_settings is not None:
|
||||||
self._wait_for_shutdown = 2
|
self._servers_from_dict(server_settings)
|
||||||
self._cache_max_messages = 1000
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def servers(self) -> List[ServerSettings]:
|
def servers(self) -> List[ServerSettings]:
|
||||||
@ -37,26 +46,34 @@ class BotSettings(ConfigurationModelABC):
|
|||||||
def cache_max_messages(self) -> int:
|
def cache_max_messages(self) -> int:
|
||||||
return self._cache_max_messages
|
return self._cache_max_messages
|
||||||
|
|
||||||
def from_dict(self, settings: dict):
|
def _servers_from_dict(self, settings: dict):
|
||||||
try:
|
|
||||||
self._technicians = settings["Technicians"]
|
|
||||||
self._wait_for_restart = settings["WaitForRestart"]
|
|
||||||
self._wait_for_shutdown = settings["WaitForShutdown"]
|
|
||||||
settings.pop("Technicians")
|
|
||||||
settings.pop("WaitForRestart")
|
|
||||||
settings.pop("WaitForShutdown")
|
|
||||||
|
|
||||||
if "CacheMaxMessages" in settings:
|
|
||||||
self._cache_max_messages = settings["CacheMaxMessages"]
|
|
||||||
settings.pop("CacheMaxMessages")
|
|
||||||
|
|
||||||
servers = List(ServerSettings)
|
servers = List(ServerSettings)
|
||||||
for s in settings:
|
for s in settings:
|
||||||
st = ServerSettings()
|
settings[s]["id"] = int(s)
|
||||||
settings[s]["Id"] = s
|
st = JSONProcessor.process(ServerSettings, settings[s])
|
||||||
st.from_dict(settings[s])
|
|
||||||
servers.append(st)
|
servers.append(st)
|
||||||
self._servers = servers
|
self._servers = servers
|
||||||
except Exception as e:
|
|
||||||
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
# def from_dict(self, settings: dict):
|
||||||
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
# try:
|
||||||
|
# self._technicians = settings["Technicians"]
|
||||||
|
# self._wait_for_restart = settings["WaitForRestart"]
|
||||||
|
# self._wait_for_shutdown = settings["WaitForShutdown"]
|
||||||
|
# settings.pop("Technicians")
|
||||||
|
# settings.pop("WaitForRestart")
|
||||||
|
# settings.pop("WaitForShutdown")
|
||||||
|
#
|
||||||
|
# if "CacheMaxMessages" in settings:
|
||||||
|
# self._cache_max_messages = settings["CacheMaxMessages"]
|
||||||
|
# settings.pop("CacheMaxMessages")
|
||||||
|
#
|
||||||
|
# servers = List(ServerSettings)
|
||||||
|
# for s in settings:
|
||||||
|
# st = ServerSettings()
|
||||||
|
# settings[s]["Id"] = s
|
||||||
|
# st.from_dict(settings[s])
|
||||||
|
# servers.append(st)
|
||||||
|
# self._servers = servers
|
||||||
|
# except Exception as e:
|
||||||
|
# Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
||||||
|
# Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
import traceback
|
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
||||||
from cpl_core.console import Console
|
|
||||||
|
|
||||||
|
|
||||||
class ServerSettings(ConfigurationModelABC):
|
class ServerSettings(ConfigurationModelABC):
|
||||||
def __init__(self):
|
def __init__(
|
||||||
|
self,
|
||||||
|
id: int = None,
|
||||||
|
message_delete_timer: int = None,
|
||||||
|
notification_chat_id: int = None,
|
||||||
|
):
|
||||||
ConfigurationModelABC.__init__(self)
|
ConfigurationModelABC.__init__(self)
|
||||||
|
|
||||||
self._id: int = 0
|
self._id: int = id
|
||||||
self._message_delete_timer: int = 0
|
self._message_delete_timer: int = message_delete_timer
|
||||||
|
self._notification_chat_id: int = notification_chat_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> int:
|
def id(self) -> int:
|
||||||
@ -19,10 +22,15 @@ class ServerSettings(ConfigurationModelABC):
|
|||||||
def message_delete_timer(self) -> int:
|
def message_delete_timer(self) -> int:
|
||||||
return self._message_delete_timer
|
return self._message_delete_timer
|
||||||
|
|
||||||
def from_dict(self, settings: dict):
|
@property
|
||||||
try:
|
def notification_chat_id(self) -> int:
|
||||||
self._id = int(settings["Id"])
|
return self._notification_chat_id
|
||||||
self._message_delete_timer = int(settings["MessageDeleteTimer"])
|
|
||||||
except Exception as e:
|
# def from_dict(self, settings: dict):
|
||||||
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings")
|
# try:
|
||||||
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
# self._id = int(settings["Id"])
|
||||||
|
# self._message_delete_timer = int(settings["MessageDeleteTimer"])
|
||||||
|
# self._notification_chat_id = int(settings["NotificationChatId"])
|
||||||
|
# except Exception as e:
|
||||||
|
# Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in settings")
|
||||||
|
# Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
||||||
|
@ -3,6 +3,7 @@ from abc import ABC, abstractmethod
|
|||||||
from cpl_query.extension import List
|
from cpl_query.extension import List
|
||||||
|
|
||||||
from bot_data.model.achievement import Achievement
|
from bot_data.model.achievement import Achievement
|
||||||
|
from bot_data.model.user_got_achievement import UserGotAchievement
|
||||||
|
|
||||||
|
|
||||||
class AchievementRepositoryABC(ABC):
|
class AchievementRepositoryABC(ABC):
|
||||||
@ -22,6 +23,10 @@ class AchievementRepositoryABC(ABC):
|
|||||||
def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]:
|
def get_achievements_by_server_id(self, server_id: int) -> List[Achievement]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]:
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def add_achievement(self, achievement: Achievement):
|
def add_achievement(self, achievement: Achievement):
|
||||||
pass
|
pass
|
||||||
@ -33,3 +38,11 @@ class AchievementRepositoryABC(ABC):
|
|||||||
@abstractmethod
|
@abstractmethod
|
||||||
def delete_achievement(self, achievement: Achievement):
|
def delete_achievement(self, achievement: Achievement):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def add_user_got_achievement(self, join: UserGotAchievement):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def delete_user_got_achievement(self, join: UserGotAchievement):
|
||||||
|
pass
|
||||||
|
@ -53,6 +53,25 @@ class AchievementsMigration(MigrationABC):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._cursor.execute(
|
||||||
|
str(
|
||||||
|
f"""
|
||||||
|
CREATE TABLE IF NOT EXISTS `UserGotAchievements` (
|
||||||
|
`Id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||||
|
`UserId` BIGINT,
|
||||||
|
`AchievementId` BIGINT,
|
||||||
|
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||||
|
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||||
|
PRIMARY KEY(`Id`),
|
||||||
|
FOREIGN KEY (`UserId`) REFERENCES `Users`(`UserId`),
|
||||||
|
FOREIGN KEY (`AchievementId`) REFERENCES `Achievements`(`Id`)
|
||||||
|
);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# A join table history between users and achievements is not necessary.
|
||||||
|
|
||||||
self._cursor.execute(str(f"""ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
self._cursor.execute(str(f"""ALTER TABLE Users ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
||||||
self._cursor.execute(str(f"""ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
self._cursor.execute(str(f"""ALTER TABLE Users ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
||||||
self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""))
|
||||||
|
99
kdb-bot/src/bot_data/model/user_got_achievement.py
Normal file
99
kdb-bot/src/bot_data/model/user_got_achievement.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from cpl_core.database import TableABC
|
||||||
|
|
||||||
|
from bot_data.model.achievement import Achievement
|
||||||
|
from bot_data.model.server import Server
|
||||||
|
from bot_data.model.user import User
|
||||||
|
|
||||||
|
|
||||||
|
class UserGotAchievement(TableABC):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
user: Optional[User],
|
||||||
|
achievement: Optional[Achievement],
|
||||||
|
server: Optional[Server],
|
||||||
|
created_at: datetime = None,
|
||||||
|
modified_at: datetime = None,
|
||||||
|
id=0,
|
||||||
|
):
|
||||||
|
self._id = id
|
||||||
|
self._user = user
|
||||||
|
self._achievement = achievement
|
||||||
|
self._server = server
|
||||||
|
|
||||||
|
TableABC.__init__(self)
|
||||||
|
self._created_at = created_at if created_at is not None else self._created_at
|
||||||
|
self._modified_at = modified_at if modified_at is not None else self._modified_at
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self) -> int:
|
||||||
|
return self._id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user(self) -> User:
|
||||||
|
return self._user
|
||||||
|
|
||||||
|
@property
|
||||||
|
def achievement(self) -> Achievement:
|
||||||
|
return self._achievement
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_select_all_string() -> str:
|
||||||
|
return str(
|
||||||
|
f"""
|
||||||
|
SELECT * FROM `UserGotAchievements`;
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_select_by_id_string(id: int) -> str:
|
||||||
|
return str(
|
||||||
|
f"""
|
||||||
|
SELECT * FROM `UserGotAchievements`
|
||||||
|
WHERE `Id` = {id};
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_select_by_user_id_string(id: int) -> str:
|
||||||
|
return str(
|
||||||
|
f"""
|
||||||
|
SELECT * FROM `UserGotAchievements`
|
||||||
|
WHERE `UserId` = {id};
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def insert_string(self) -> str:
|
||||||
|
return str(
|
||||||
|
f"""
|
||||||
|
INSERT INTO `UserGotAchievements` (
|
||||||
|
`UserId`, `AchievementId`
|
||||||
|
) VALUES (
|
||||||
|
{self._user.id},
|
||||||
|
{self._achievement.id}
|
||||||
|
);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def udpate_string(self) -> str:
|
||||||
|
return str(
|
||||||
|
f"""
|
||||||
|
UPDATE `UserGotAchievements`
|
||||||
|
SET `UserId` = '{self._user.id}',
|
||||||
|
`AchievementId` = '{self._achievement.id}'
|
||||||
|
WHERE `Id` = {self._id};
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def delete_string(self) -> str:
|
||||||
|
return str(
|
||||||
|
f"""
|
||||||
|
DELETE FROM `UserGotAchievements`
|
||||||
|
WHERE `Id` = {self._id};
|
||||||
|
"""
|
||||||
|
)
|
@ -4,7 +4,9 @@ from cpl_query.extension import List
|
|||||||
from bot_core.logging.database_logger import DatabaseLogger
|
from bot_core.logging.database_logger import DatabaseLogger
|
||||||
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||||
|
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||||
from bot_data.model.achievement import Achievement
|
from bot_data.model.achievement import Achievement
|
||||||
|
from bot_data.model.user_got_achievement import UserGotAchievement
|
||||||
|
|
||||||
|
|
||||||
class AchievementRepositoryService(AchievementRepositoryABC):
|
class AchievementRepositoryService(AchievementRepositoryABC):
|
||||||
@ -13,11 +15,13 @@ class AchievementRepositoryService(AchievementRepositoryABC):
|
|||||||
logger: DatabaseLogger,
|
logger: DatabaseLogger,
|
||||||
db_context: DatabaseContextABC,
|
db_context: DatabaseContextABC,
|
||||||
servers: ServerRepositoryABC,
|
servers: ServerRepositoryABC,
|
||||||
|
users: UserRepositoryABC,
|
||||||
):
|
):
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
self._context = db_context
|
self._context = db_context
|
||||||
|
|
||||||
self._servers = servers
|
self._servers = servers
|
||||||
|
self._users = users
|
||||||
|
|
||||||
AchievementRepositoryABC.__init__(self)
|
AchievementRepositoryABC.__init__(self)
|
||||||
|
|
||||||
@ -33,6 +37,15 @@ class AchievementRepositoryService(AchievementRepositoryABC):
|
|||||||
id=result[0],
|
id=result[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _join_from_result(self, result: tuple):
|
||||||
|
return UserGotAchievement(
|
||||||
|
self._users.get_user_by_id(result[1]),
|
||||||
|
self.get_achievement_by_id(result[2]),
|
||||||
|
self._servers.get_server_by_id(result[3]),
|
||||||
|
result[5],
|
||||||
|
id=result[0],
|
||||||
|
)
|
||||||
|
|
||||||
def get_achievements(self) -> List[Achievement]:
|
def get_achievements(self) -> List[Achievement]:
|
||||||
achievements = List(Achievement)
|
achievements = List(Achievement)
|
||||||
self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_all_string()}")
|
self._logger.trace(__name__, f"Send SQL command: {Achievement.get_select_all_string()}")
|
||||||
@ -59,6 +72,23 @@ class AchievementRepositoryService(AchievementRepositoryABC):
|
|||||||
|
|
||||||
return achievements
|
return achievements
|
||||||
|
|
||||||
|
def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]:
|
||||||
|
achievements = List(Achievement)
|
||||||
|
achievements_joins = List(UserGotAchievement)
|
||||||
|
self._logger.trace(__name__, f"Send SQL command: {UserGotAchievement.get_select_by_user_id_string(user_id)}")
|
||||||
|
results = self._context.select(UserGotAchievement.get_select_all_string())
|
||||||
|
for result in results:
|
||||||
|
self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}")
|
||||||
|
achievements_joins.append(self._join_from_result(result))
|
||||||
|
|
||||||
|
for achievements_join in achievements_joins:
|
||||||
|
results = self._context.select(Achievement.get_select_by_id_string(achievements_join.achievement.id))
|
||||||
|
for result in results:
|
||||||
|
self._logger.trace(__name__, f"Got Achievement with id {result[0]}")
|
||||||
|
achievements.append(self._from_result(result))
|
||||||
|
|
||||||
|
return achievements
|
||||||
|
|
||||||
def add_achievement(self, achievement: Achievement):
|
def add_achievement(self, achievement: Achievement):
|
||||||
self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}")
|
self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}")
|
||||||
self._context.cursor.execute(achievement.insert_string)
|
self._context.cursor.execute(achievement.insert_string)
|
||||||
@ -70,3 +100,11 @@ class AchievementRepositoryService(AchievementRepositoryABC):
|
|||||||
def delete_achievement(self, achievement: Achievement):
|
def delete_achievement(self, achievement: Achievement):
|
||||||
self._logger.trace(__name__, f"Send SQL command: {achievement.delete_string}")
|
self._logger.trace(__name__, f"Send SQL command: {achievement.delete_string}")
|
||||||
self._context.cursor.execute(achievement.delete_string)
|
self._context.cursor.execute(achievement.delete_string)
|
||||||
|
|
||||||
|
def add_user_got_achievement(self, join: UserGotAchievement):
|
||||||
|
self._logger.trace(__name__, f"Send SQL command: {join.insert_string}")
|
||||||
|
self._context.cursor.execute(join.insert_string)
|
||||||
|
|
||||||
|
def delete_user_got_achievement(self, join: UserGotAchievement):
|
||||||
|
self._logger.trace(__name__, f"Send SQL command: {join.delete_string}")
|
||||||
|
self._context.cursor.execute(join.delete_string)
|
||||||
|
78
kdb-bot/src/modules/achievements/achievement_service.py
Normal file
78
kdb-bot/src/modules/achievements/achievement_service.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
from cpl_core.configuration import ConfigurationABC
|
||||||
|
from cpl_core.database.context import DatabaseContextABC
|
||||||
|
from cpl_core.logging import LoggerABC
|
||||||
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
|
from cpl_translation import TranslatePipe
|
||||||
|
|
||||||
|
from bot_core.configuration.server_settings import ServerSettings
|
||||||
|
from bot_core.service.message_service import MessageService
|
||||||
|
from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC
|
||||||
|
from bot_data.model.achievement import Achievement
|
||||||
|
from bot_data.model.user import User
|
||||||
|
from bot_data.model.user_got_achievement import UserGotAchievement
|
||||||
|
|
||||||
|
|
||||||
|
class AchievementService:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
config: ConfigurationABC,
|
||||||
|
logger: LoggerABC,
|
||||||
|
bot: DiscordBotServiceABC,
|
||||||
|
achievements: AchievementRepositoryABC,
|
||||||
|
db: DatabaseContextABC,
|
||||||
|
message_service: MessageService,
|
||||||
|
t: TranslatePipe,
|
||||||
|
):
|
||||||
|
self._config = config
|
||||||
|
self._logger = logger
|
||||||
|
self._bot = bot
|
||||||
|
self._achievements = achievements
|
||||||
|
self._db = db
|
||||||
|
self._message_service = message_service
|
||||||
|
self._t = t
|
||||||
|
|
||||||
|
def _match(self, value: str, operator: str, expected_value: str) -> bool:
|
||||||
|
match operator:
|
||||||
|
case "==":
|
||||||
|
return value == expected_value
|
||||||
|
case "!=":
|
||||||
|
return value != expected_value
|
||||||
|
case "<=":
|
||||||
|
return value <= expected_value
|
||||||
|
case ">=":
|
||||||
|
return value >= expected_value
|
||||||
|
case "<":
|
||||||
|
return value < expected_value
|
||||||
|
case ">":
|
||||||
|
return value > expected_value
|
||||||
|
case _:
|
||||||
|
raise ValueError(f"Invalid operator: ${operator}")
|
||||||
|
|
||||||
|
def has_user_achievement_already(self, user: User, achievement: Achievement) -> bool:
|
||||||
|
user_achievements = self._achievements.get_achievements_by_user_id(user.id)
|
||||||
|
return user_achievements.where(lambda x: x.name == achievement.name).count() > 0
|
||||||
|
|
||||||
|
def has_user_achievement(self, user: User, achievement: Achievement) -> bool:
|
||||||
|
return self._match(str(getattr(user, achievement.attribute)), achievement.operator, achievement.value)
|
||||||
|
|
||||||
|
async def validate_achievements_for_user(self, user: User):
|
||||||
|
achievements = self._achievements.get_achievements_by_server_id(user.server.id)
|
||||||
|
for achievement in achievements:
|
||||||
|
if self.has_user_achievement_already(user, achievement) and not self.has_user_achievement(
|
||||||
|
user, achievement
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
self._achievements.add_user_got_achievement(UserGotAchievement(user, achievement, user.server))
|
||||||
|
self._db.save_changes()
|
||||||
|
await self._send_achievement_notification(user.server.discord_id, user.discord_id, achievement.name)
|
||||||
|
|
||||||
|
async def _send_achievement_notification(self, guild_id: int, member_id: int, achievement_name: str):
|
||||||
|
member = self._bot.get_guild(guild_id).get_member(member_id)
|
||||||
|
|
||||||
|
settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild_id}")
|
||||||
|
await self._message_service.send_channel_message(
|
||||||
|
self._bot.get_channel(settings.notification_chat_id),
|
||||||
|
self._t.transform("modules.achievements.got_new_achievement").format(member.mention, achievement_name),
|
||||||
|
is_persistent=True,
|
||||||
|
)
|
@ -1,10 +1,13 @@
|
|||||||
from cpl_core.configuration import ConfigurationABC
|
from cpl_core.configuration import ConfigurationABC
|
||||||
from cpl_core.dependency_injection import ServiceCollectionABC
|
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||||
from cpl_core.environment import ApplicationEnvironmentABC
|
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 cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
||||||
|
|
||||||
from bot_core.abc.module_abc import ModuleABC
|
from bot_core.abc.module_abc import ModuleABC
|
||||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||||
|
from modules.achievements.achievement_service import AchievementService
|
||||||
|
from modules.achievements.events.achievement_on_message_event import AchievementOnMessageEvent
|
||||||
|
|
||||||
|
|
||||||
class AchievementsModule(ModuleABC):
|
class AchievementsModule(ModuleABC):
|
||||||
@ -15,4 +18,5 @@ class AchievementsModule(ModuleABC):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||||
pass
|
services.add_transient(AchievementService)
|
||||||
|
self._dc.add_event(DiscordEventTypesEnum.on_message.value, AchievementOnMessageEvent)
|
||||||
|
1
kdb-bot/src/modules/achievements/events/__init__.py
Normal file
1
kdb-bot/src/modules/achievements/events/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
# imports
|
@ -0,0 +1,43 @@
|
|||||||
|
import discord
|
||||||
|
from cpl_core.database.context import DatabaseContextABC
|
||||||
|
from cpl_core.logging import LoggerABC
|
||||||
|
from cpl_discord.events import OnMessageABC
|
||||||
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
|
|
||||||
|
from bot_core.helper.event_checks import EventChecks
|
||||||
|
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||||
|
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||||
|
from modules.achievements.achievement_service import AchievementService
|
||||||
|
|
||||||
|
|
||||||
|
class AchievementOnMessageEvent(OnMessageABC):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
logger: LoggerABC,
|
||||||
|
bot: DiscordBotServiceABC,
|
||||||
|
achievements: AchievementService,
|
||||||
|
db: DatabaseContextABC,
|
||||||
|
servers: ServerRepositoryABC,
|
||||||
|
users: UserRepositoryABC,
|
||||||
|
):
|
||||||
|
OnMessageABC.__init__(self)
|
||||||
|
|
||||||
|
self._logger = logger
|
||||||
|
self._bot = bot
|
||||||
|
self._achievements = achievements
|
||||||
|
self._db = db
|
||||||
|
self._servers = servers
|
||||||
|
self._users = users
|
||||||
|
|
||||||
|
@EventChecks.check_is_ready()
|
||||||
|
async def on_message(self, message: discord.Message):
|
||||||
|
if message.author.bot:
|
||||||
|
return
|
||||||
|
|
||||||
|
server = self._servers.get_server_by_discord_id(message.guild.id)
|
||||||
|
user = self._users.get_user_by_discord_id_and_server_id(message.author.id, server.id)
|
||||||
|
|
||||||
|
user.message_count += 1
|
||||||
|
self._db.save_changes()
|
||||||
|
|
||||||
|
await self._achievements.validate_achievements_for_user(user)
|
@ -1,28 +0,0 @@
|
|||||||
import traceback
|
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
|
|
||||||
|
|
||||||
class LevelServerSettings(ConfigurationModelABC):
|
|
||||||
def __init__(self):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._id: int = 0
|
|
||||||
self._changed_level_notification_channel = 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def id(self) -> int:
|
|
||||||
return self._id
|
|
||||||
|
|
||||||
@property
|
|
||||||
def changed_level_notification_channel(self) -> int:
|
|
||||||
return self._changed_level_notification_channel
|
|
||||||
|
|
||||||
def from_dict(self, settings: dict):
|
|
||||||
try:
|
|
||||||
self._id = int(settings["Id"])
|
|
||||||
self._changed_level_notification_channel = int(settings["ChangedLevelNotificationChannelId"])
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
|
||||||
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
|
@ -1,31 +0,0 @@
|
|||||||
import traceback
|
|
||||||
|
|
||||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
|
||||||
from cpl_core.console import Console
|
|
||||||
from cpl_query.extension import List
|
|
||||||
|
|
||||||
from modules.level.configuration.level_server_settings import LevelServerSettings
|
|
||||||
|
|
||||||
|
|
||||||
class LevelSettings(ConfigurationModelABC):
|
|
||||||
def __init__(self):
|
|
||||||
ConfigurationModelABC.__init__(self)
|
|
||||||
|
|
||||||
self._servers: List[LevelServerSettings] = List()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def servers(self) -> List[LevelServerSettings]:
|
|
||||||
return self._servers
|
|
||||||
|
|
||||||
def from_dict(self, settings: dict):
|
|
||||||
try:
|
|
||||||
servers = List(LevelServerSettings)
|
|
||||||
for s in settings:
|
|
||||||
st = LevelServerSettings()
|
|
||||||
settings[s]["Id"] = s
|
|
||||||
st.from_dict(settings[s])
|
|
||||||
servers.append(st)
|
|
||||||
self._servers = servers
|
|
||||||
except Exception as e:
|
|
||||||
Console.error(f"[ ERROR ] [ {__name__} ]: Reading error in {type(self).__name__} settings")
|
|
||||||
Console.error(f"[ EXCEPTION ] [ {__name__} ]: {e} -> {traceback.format_exc()}")
|
|
@ -6,13 +6,13 @@ from cpl_discord.container import Guild, Role, Member
|
|||||||
from cpl_discord.service import DiscordBotServiceABC
|
from cpl_discord.service import DiscordBotServiceABC
|
||||||
from cpl_translation import TranslatePipe
|
from cpl_translation import TranslatePipe
|
||||||
|
|
||||||
|
from bot_core.configuration.server_settings import ServerSettings
|
||||||
from bot_core.service.message_service import MessageService
|
from bot_core.service.message_service import MessageService
|
||||||
from bot_data.model.level import Level
|
from bot_data.model.level import Level
|
||||||
from bot_data.model.user import User
|
from bot_data.model.user import User
|
||||||
from bot_data.service.level_repository_service import LevelRepositoryService
|
from bot_data.service.level_repository_service import LevelRepositoryService
|
||||||
from bot_data.service.server_repository_service import ServerRepositoryService
|
from bot_data.service.server_repository_service import ServerRepositoryService
|
||||||
from bot_data.service.user_repository_service import UserRepositoryService
|
from bot_data.service.user_repository_service import UserRepositoryService
|
||||||
from modules.level.configuration.level_server_settings import LevelServerSettings
|
|
||||||
|
|
||||||
|
|
||||||
class LevelService:
|
class LevelService:
|
||||||
@ -75,9 +75,9 @@ class LevelService:
|
|||||||
self._logger.error(__name__, f"Adding role {level_role.name} to {member.name} failed!", e)
|
self._logger.error(__name__, f"Adding role {level_role.name} to {member.name} failed!", e)
|
||||||
|
|
||||||
if notification_needed:
|
if notification_needed:
|
||||||
level_settings: LevelServerSettings = self._config.get_configuration(f"LevelServerSettings_{guild.id}")
|
settings: ServerSettings = self._config.get_configuration(f"ServerSettings_{guild.id}")
|
||||||
await self._message_service.send_channel_message(
|
await self._message_service.send_channel_message(
|
||||||
self._bot.get_channel(level_settings.changed_level_notification_channel),
|
self._bot.get_channel(settings.notification_chat_id),
|
||||||
self._t.transform("modules.level.new_level_message").format(member.mention, level.name),
|
self._t.transform("modules.level.new_level_message").format(member.mention, level.name),
|
||||||
is_persistent=True,
|
is_persistent=True,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user