Compare commits
1 Commits
dd6b609094
...
1.1.10
Author | SHA1 | Date | |
---|---|---|---|
eeda0405f3 |
18
.gitmodules
vendored
18
.gitmodules
vendored
@@ -1,9 +1,9 @@
|
||||
[submodule "bot/src/bot/config"]
|
||||
path = bot/src/bot/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.config.git
|
||||
[submodule "bot/src/bot_api/config"]
|
||||
path = bot/src/bot_api/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.api.config.git
|
||||
[submodule "bot/docker"]
|
||||
path = bot/docker
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.docker.git
|
||||
[submodule "kdb-bot/src/bot/config"]
|
||||
path = kdb-bot/src/bot/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.config.git
|
||||
[submodule "kdb-bot/src/bot_api/config"]
|
||||
path = kdb-bot/src/bot_api/config
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.api.config.git
|
||||
[submodule "kdb-bot/docker"]
|
||||
path = kdb-bot/docker
|
||||
url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.docker.git
|
||||
|
@@ -1,106 +0,0 @@
|
||||
from cpl_core.application import StartupExtensionABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.migration.achievements_migration import AchievementsMigration
|
||||
from bot_data.migration.api_key_migration import ApiKeyMigration
|
||||
from bot_data.migration.api_migration import ApiMigration
|
||||
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
|
||||
from bot_data.migration.auto_role_migration import AutoRoleMigration
|
||||
from bot_data.migration.birthday_migration import BirthdayMigration
|
||||
from bot_data.migration.config_feature_flags_migration import (
|
||||
ConfigFeatureFlagsMigration,
|
||||
)
|
||||
from bot_data.migration.config_migration import ConfigMigration
|
||||
from bot_data.migration.db_history_migration import DBHistoryMigration
|
||||
from bot_data.migration.default_role_migration import DefaultRoleMigration
|
||||
from bot_data.migration.fix_updates_migration import FixUpdatesMigration
|
||||
from bot_data.migration.fix_user_history_migration import FixUserHistoryMigration
|
||||
from bot_data.migration.initial_migration import InitialMigration
|
||||
from bot_data.migration.level_migration import LevelMigration
|
||||
from bot_data.migration.remove_stats_migration import RemoveStatsMigration
|
||||
from bot_data.migration.short_role_name_migration import ShortRoleNameMigration
|
||||
from bot_data.migration.short_role_name_only_highest_migration import (
|
||||
ShortRoleNameOnlyHighestMigration,
|
||||
)
|
||||
from bot_data.migration.stats_migration import StatsMigration
|
||||
from bot_data.migration.steam_special_offer_migration import SteamSpecialOfferMigration
|
||||
from bot_data.migration.user_joined_game_server_migration import (
|
||||
UserJoinedGameServerMigration,
|
||||
)
|
||||
from bot_data.migration.user_message_count_per_hour_migration import (
|
||||
UserMessageCountPerHourMigration,
|
||||
)
|
||||
from bot_data.migration.user_warning_migration import UserWarningMigration
|
||||
from bot_data.service.migration_service import MigrationService
|
||||
|
||||
|
||||
class StartupMigrationExtension(StartupExtensionABC):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
pass
|
||||
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
services.add_transient(MigrationService)
|
||||
services.add_transient(MigrationABC, InitialMigration)
|
||||
services.add_transient(
|
||||
MigrationABC, AutoRoleMigration
|
||||
) # 03.10.2022 #54 - 0.2.2
|
||||
services.add_transient(MigrationABC, ApiMigration) # 15.10.2022 #70 - 0.3.0
|
||||
services.add_transient(MigrationABC, LevelMigration) # 06.11.2022 #25 - 0.3.0
|
||||
services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0
|
||||
services.add_transient(
|
||||
MigrationABC, AutoRoleFix1Migration
|
||||
) # 30.12.2022 #151 - 0.3.0
|
||||
services.add_transient(
|
||||
MigrationABC, UserMessageCountPerHourMigration
|
||||
) # 11.01.2023 #168 - 0.3.1
|
||||
services.add_transient(MigrationABC, ApiKeyMigration) # 09.02.2023 #162 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, UserJoinedGameServerMigration
|
||||
) # 12.02.2023 #181 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, RemoveStatsMigration
|
||||
) # 19.02.2023 #190 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, UserWarningMigration
|
||||
) # 21.02.2023 #35 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, DBHistoryMigration
|
||||
) # 06.03.2023 #246 - 1.0.0
|
||||
services.add_transient(
|
||||
MigrationABC, AchievementsMigration
|
||||
) # 14.06.2023 #268 - 1.1.0
|
||||
services.add_transient(MigrationABC, ConfigMigration) # 19.07.2023 #127 - 1.1.0
|
||||
services.add_transient(
|
||||
MigrationABC, ConfigFeatureFlagsMigration
|
||||
) # 15.08.2023 #334 - 1.1.0
|
||||
services.add_transient(
|
||||
MigrationABC, DefaultRoleMigration
|
||||
) # 24.09.2023 #360 - 1.1.3
|
||||
services.add_transient(
|
||||
MigrationABC, ShortRoleNameMigration
|
||||
) # 28.09.2023 #378 - 1.1.7
|
||||
services.add_transient(
|
||||
MigrationABC, FixUpdatesMigration
|
||||
) # 28.09.2023 #378 - 1.1.7
|
||||
services.add_transient(
|
||||
MigrationABC, ShortRoleNameOnlyHighestMigration
|
||||
) # 02.10.2023 #391 - 1.1.9
|
||||
services.add_transient(
|
||||
MigrationABC, FixUserHistoryMigration
|
||||
) # 10.10.2023 #401 - 1.2.0
|
||||
services.add_transient(
|
||||
MigrationABC, BirthdayMigration
|
||||
) # 10.10.2023 #401 - 1.2.0
|
||||
services.add_transient(
|
||||
MigrationABC, SteamSpecialOfferMigration
|
||||
) # 10.10.2023 #188 - 1.2.0
|
@@ -1,30 +0,0 @@
|
||||
import asyncio
|
||||
from abc import abstractmethod
|
||||
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
from discord.ext import commands
|
||||
|
||||
from bot_core.logging.task_logger import TaskLogger
|
||||
|
||||
|
||||
class TaskABC(commands.Cog):
|
||||
@abstractmethod
|
||||
def __init__(self):
|
||||
commands.Cog.__init__(self)
|
||||
|
||||
@ServiceProviderABC.inject
|
||||
async def _wait_until_ready(
|
||||
self, config: ConfigurationABC, logger: TaskLogger, bot: DiscordBotServiceABC
|
||||
):
|
||||
logger.debug(__name__, f"Waiting before {type(self).__name__}")
|
||||
await bot.wait_until_ready()
|
||||
|
||||
async def wait():
|
||||
is_ready = config.get_configuration("IS_READY")
|
||||
if is_ready != "true":
|
||||
await asyncio.sleep(1)
|
||||
await wait()
|
||||
|
||||
await wait()
|
@@ -1,15 +0,0 @@
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
from cpl_core.time import TimeFormatSettings
|
||||
|
||||
from bot_core.abc.custom_file_logger_abc import CustomFileLoggerABC
|
||||
|
||||
|
||||
class TaskLogger(CustomFileLoggerABC):
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
time_format: TimeFormatSettings,
|
||||
env: ApplicationEnvironmentABC,
|
||||
):
|
||||
CustomFileLoggerABC.__init__(self, "Task", config, time_format, env)
|
@@ -1,32 +0,0 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_data.model.steam_special_offer import SteamSpecialOffer
|
||||
|
||||
|
||||
class SteamSpecialOfferRepositoryABC(ABC):
|
||||
@abstractmethod
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_steam_special_offers(self) -> List[SteamSpecialOffer]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_steam_special_offer_by_name(self, name: str) -> SteamSpecialOffer:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_steam_special_offer(self, steam_special_offer: SteamSpecialOffer):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def update_steam_special_offer(self, steam_special_offer: SteamSpecialOffer):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_steam_special_offer(self, steam_special_offer: SteamSpecialOffer):
|
||||
pass
|
@@ -1,84 +0,0 @@
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.db_context import DBContext
|
||||
|
||||
|
||||
class BirthdayMigration(MigrationABC):
|
||||
name = "1.2.0_BirthdayMigration"
|
||||
|
||||
def __init__(self, logger: DatabaseLogger, db: DBContext):
|
||||
MigrationABC.__init__(self)
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
def upgrade(self):
|
||||
self._logger.debug(__name__, "Running upgrade")
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE Users
|
||||
ADD Birthday DATE NULL AFTER MessageCount;
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE UsersHistory
|
||||
ADD Birthday DATE NULL AFTER MessageCount;
|
||||
"""
|
||||
)
|
||||
)
|
||||
self._exec(__file__, "users.sql")
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_Server
|
||||
ADD XpForBirthday BIGINT(20) NOT NULL DEFAULT 0 AFTER XpPerAchievement;
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_ServerHistory
|
||||
ADD XpForBirthday BIGINT(20) NOT NULL DEFAULT 0 AFTER XpPerAchievement;
|
||||
"""
|
||||
)
|
||||
)
|
||||
self._exec(__file__, "config/server.sql")
|
||||
|
||||
def downgrade(self):
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE Users DROP COLUMN Birthday;
|
||||
"""
|
||||
)
|
||||
)
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE UsersHistory DROP COLUMN Birthday;
|
||||
"""
|
||||
)
|
||||
)
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_Server DROP COLUMN XpForBirthday;
|
||||
"""
|
||||
)
|
||||
)
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_ServerHistory DROP COLUMN XpForBirthday;
|
||||
"""
|
||||
)
|
||||
)
|
@@ -1,45 +0,0 @@
|
||||
ALTER TABLE `Users`
|
||||
CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6);
|
||||
|
||||
ALTER TABLE `Users`
|
||||
CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `UsersHistory`
|
||||
(
|
||||
`Id` BIGINT(20) NOT NULL,
|
||||
`DiscordId` BIGINT(20) NOT NULL,
|
||||
`XP` BIGINT(20) NOT NULL DEFAULT 0,
|
||||
`ReactionCount` BIGINT(20) NOT NULL DEFAULT 0,
|
||||
`MessageCount` BIGINT(20) NOT NULL DEFAULT 0,
|
||||
`Birthday` DATE NULL,
|
||||
`ServerId` BIGINT(20) DEFAULT NULL,
|
||||
`Deleted` BOOL DEFAULT FALSE,
|
||||
`DateFrom` DATETIME(6) NOT NULL,
|
||||
`DateTo` DATETIME(6) NOT NULL
|
||||
);
|
||||
|
||||
DROP TRIGGER IF EXISTS `TR_UsersUpdate`;
|
||||
|
||||
CREATE TRIGGER `TR_UsersUpdate`
|
||||
AFTER UPDATE
|
||||
ON `Users`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO `UsersHistory` (`Id`, `DiscordId`, `XP`, `ReactionCount`, `MessageCount`, `Birthday`, `ServerId`,
|
||||
`DateFrom`, `DateTo`)
|
||||
VALUES (OLD.UserId, OLD.DiscordId, OLD.XP, OLD.ReactionCount, OLD.MessageCount, OLD.Birthday, OLD.ServerId,
|
||||
OLD.LastModifiedAt, CURRENT_TIMESTAMP(6));
|
||||
END;
|
||||
|
||||
DROP TRIGGER IF EXISTS `TR_UsersDelete`;
|
||||
|
||||
CREATE TRIGGER `TR_UsersDelete`
|
||||
AFTER DELETE
|
||||
ON `Users`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
INSERT INTO `UsersHistory` (`Id`, `DiscordId`, `XP`, `ReactionCount`, `MessageCount`, `Birthday`, `ServerId`,
|
||||
`Deleted`, `DateFrom`, `DateTo`)
|
||||
VALUES (OLD.UserId, OLD.DiscordId, OLD.XP, OLD.ReactionCount, OLD.MessageCount, OLD.Birthday, OLD.ServerId, TRUE,
|
||||
OLD.LastModifiedAt, CURRENT_TIMESTAMP(6));
|
||||
END;
|
@@ -1,45 +0,0 @@
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.db_context import DBContext
|
||||
|
||||
|
||||
class FixUserHistoryMigration(MigrationABC):
|
||||
name = "1.2.0_FixUserHistoryMigration"
|
||||
|
||||
def __init__(self, logger: DatabaseLogger, db: DBContext):
|
||||
MigrationABC.__init__(self)
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
def upgrade(self):
|
||||
self._logger.debug(__name__, "Running upgrade")
|
||||
|
||||
# fix 1.1.0_AchievementsMigration
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""ALTER TABLE UsersHistory ADD COLUMN IF NOT EXISTS ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;"""
|
||||
)
|
||||
)
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""ALTER TABLE UsersHistory ADD COLUMN IF NOT EXISTS MessageCount BIGINT NOT NULL DEFAULT 0 AFTER ReactionCount;"""
|
||||
)
|
||||
)
|
||||
self._exec(__file__, "users.sql")
|
||||
|
||||
def downgrade(self):
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE UsersHistory DROP COLUMN MessageCount;
|
||||
"""
|
||||
)
|
||||
)
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE UsersHistory DROP COLUMN ReactionCount;
|
||||
"""
|
||||
)
|
||||
)
|
@@ -1,68 +0,0 @@
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.db_context import DBContext
|
||||
|
||||
|
||||
class SteamSpecialOfferMigration(MigrationABC):
|
||||
name = "1.2.0_SteamSpecialOfferMigration"
|
||||
|
||||
def __init__(self, logger: DatabaseLogger, db: DBContext):
|
||||
MigrationABC.__init__(self)
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._cursor = db.cursor
|
||||
|
||||
def upgrade(self):
|
||||
self._logger.debug(__name__, "Running upgrade")
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS `SteamSpecialOffers` (
|
||||
`Id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`Game` VARCHAR(255) NOT NULL,
|
||||
`OriginalPrice` FLOAT NOT NULL,
|
||||
`DiscountPrice` FLOAT NOT NULL,
|
||||
`DiscountPct` BIGINT NOT NULL,
|
||||
`CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY(`Id`)
|
||||
);
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_Server
|
||||
ADD COLUMN IF NOT EXISTS GameOfferNotificationChatId BIGINT NULL AFTER ShortRoleNameSetOnlyHighest;
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_ServerHistory
|
||||
ADD COLUMN IF NOT EXISTS GameOfferNotificationChatId BIGINT NULL AFTER ShortRoleNameSetOnlyHighest;
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
def downgrade(self):
|
||||
self._cursor.execute("DROP TABLE `SteamSpecialOffers`;")
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_Server DROP COLUMN ShortRoleNameSetOnlyHighest;
|
||||
"""
|
||||
)
|
||||
)
|
||||
self._cursor.execute(
|
||||
str(
|
||||
f"""
|
||||
ALTER TABLE CFG_ServerHistory DROP COLUMN ShortRoleNameSetOnlyHighest;
|
||||
"""
|
||||
)
|
||||
)
|
@@ -1,117 +0,0 @@
|
||||
from datetime import datetime
|
||||
|
||||
from cpl_core.database import TableABC
|
||||
|
||||
|
||||
class SteamSpecialOffer(TableABC):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
original_price: float,
|
||||
discount_price: float,
|
||||
discount_pct: int,
|
||||
created_at: datetime = None,
|
||||
modified_at: datetime = None,
|
||||
id=0,
|
||||
):
|
||||
self._id = id
|
||||
self._name = name
|
||||
self._original_price = original_price
|
||||
self._discount_price = discount_price
|
||||
self._discount_pct = discount_pct
|
||||
|
||||
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 name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, value: str):
|
||||
self._name = value
|
||||
|
||||
@property
|
||||
def original_price(self) -> float:
|
||||
return self._original_price
|
||||
|
||||
@original_price.setter
|
||||
def original_price(self, value: float):
|
||||
self._original_price = value
|
||||
|
||||
@property
|
||||
def discount_price(self) -> float:
|
||||
return self._discount_price
|
||||
|
||||
@discount_price.setter
|
||||
def discount_price(self, value: float):
|
||||
self._discount_price = value
|
||||
|
||||
@property
|
||||
def discount_pct(self) -> int:
|
||||
return self._discount_pct
|
||||
|
||||
@discount_pct.setter
|
||||
def discount_pct(self, value: int):
|
||||
self._discount_pct = value
|
||||
|
||||
@staticmethod
|
||||
def get_select_all_string() -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `SteamSpecialOffers`;
|
||||
"""
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_select_by_name_string(name: str) -> str:
|
||||
return str(
|
||||
f"""
|
||||
SELECT * FROM `SteamSpecialOffers`
|
||||
WHERE `Game` = '{name}';
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def insert_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
INSERT INTO `SteamSpecialOffers` (
|
||||
`Game`, `OriginalPrice`, `DiscountPrice`, `DiscountPct`
|
||||
) VALUES (
|
||||
'{self._name}',
|
||||
{self._original_price},
|
||||
{self._discount_price},
|
||||
{self._discount_pct}
|
||||
);
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def udpate_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
UPDATE `SteamSpecialOffers`
|
||||
SET `Game` = '{self._name}',
|
||||
`OriginalPrice` = {self._original_price},
|
||||
`DiscountPrice` = {self._discount_price},
|
||||
`DiscountPct` = {self._discount_pct}
|
||||
WHERE `Id` = {self._id};
|
||||
"""
|
||||
)
|
||||
|
||||
@property
|
||||
def delete_string(self) -> str:
|
||||
return str(
|
||||
f"""
|
||||
DELETE FROM `SteamSpecialOffers`
|
||||
WHERE `Id` = {self._id};
|
||||
"""
|
||||
)
|
@@ -1,43 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from bot_data.abc.history_table_abc import HistoryTableABC
|
||||
|
||||
|
||||
# had to name it UserWarnings instead of UserWarning because UserWarning is a builtin class
|
||||
class UserWarningsHistory(HistoryTableABC):
|
||||
def __init__(
|
||||
self,
|
||||
description: str,
|
||||
user: int,
|
||||
author: Optional[int],
|
||||
deleted: bool,
|
||||
date_from: str,
|
||||
date_to: str,
|
||||
id=0,
|
||||
):
|
||||
HistoryTableABC.__init__(self)
|
||||
|
||||
self._id = id
|
||||
self._description = description
|
||||
self._user = user
|
||||
self._author = author
|
||||
|
||||
self._deleted = deleted
|
||||
self._date_from = date_from
|
||||
self._date_to = date_to
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return self._description
|
||||
|
||||
@property
|
||||
def user(self) -> int:
|
||||
return self._user
|
||||
|
||||
@property
|
||||
def author(self) -> Optional[int]:
|
||||
return self._author
|
@@ -1,83 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.abc.steam_special_offer_repository_abc import (
|
||||
SteamSpecialOfferRepositoryABC,
|
||||
)
|
||||
from bot_data.model.steam_special_offer import SteamSpecialOffer
|
||||
|
||||
|
||||
class SteamSpecialOfferRepositoryService(SteamSpecialOfferRepositoryABC):
|
||||
def __init__(
|
||||
self,
|
||||
logger: DatabaseLogger,
|
||||
db_context: DatabaseContextABC,
|
||||
servers: ServerRepositoryABC,
|
||||
):
|
||||
self._logger = logger
|
||||
self._context = db_context
|
||||
|
||||
self._servers = servers
|
||||
|
||||
SteamSpecialOfferRepositoryABC.__init__(self)
|
||||
|
||||
@staticmethod
|
||||
def _get_value_from_result(value: any) -> Optional[any]:
|
||||
if isinstance(value, str) and "NULL" in value:
|
||||
return None
|
||||
|
||||
return value
|
||||
|
||||
def _steam_special_offer_from_result(self, sql_result: tuple) -> SteamSpecialOffer:
|
||||
return SteamSpecialOffer(
|
||||
self._get_value_from_result(sql_result[1]), # name
|
||||
float(self._get_value_from_result(sql_result[2])), # original_price
|
||||
float(self._get_value_from_result(sql_result[3])), # discount_price
|
||||
int(self._get_value_from_result(sql_result[4])), # discount_pct
|
||||
id=self._get_value_from_result(sql_result[0]), # id
|
||||
)
|
||||
|
||||
def get_steam_special_offers(self) -> List[SteamSpecialOffer]:
|
||||
steam_special_offers = List(SteamSpecialOffer)
|
||||
self._logger.trace(
|
||||
__name__, f"Send SQL command: {SteamSpecialOffer.get_select_all_string()}"
|
||||
)
|
||||
results = self._context.select(SteamSpecialOffer.get_select_all_string())
|
||||
for result in results:
|
||||
self._logger.trace(__name__, f"Get steam_special_offer with id {result[0]}")
|
||||
steam_special_offers.append(self._steam_special_offer_from_result(result))
|
||||
|
||||
return steam_special_offers
|
||||
|
||||
def get_steam_special_offer_by_name(self, name: str) -> SteamSpecialOffer:
|
||||
self._logger.trace(
|
||||
__name__,
|
||||
f"Send SQL command: {SteamSpecialOffer.get_select_by_name_string(name)}",
|
||||
)
|
||||
result = self._context.select(
|
||||
SteamSpecialOffer.get_select_by_name_string(name)
|
||||
)[0]
|
||||
|
||||
return self._steam_special_offer_from_result(result)
|
||||
|
||||
def add_steam_special_offer(self, steam_special_offer: SteamSpecialOffer):
|
||||
self._logger.trace(
|
||||
__name__, f"Send SQL command: {steam_special_offer.insert_string}"
|
||||
)
|
||||
self._context.cursor.execute(steam_special_offer.insert_string)
|
||||
|
||||
def update_steam_special_offer(self, steam_special_offer: SteamSpecialOffer):
|
||||
self._logger.trace(
|
||||
__name__, f"Send SQL command: {steam_special_offer.udpate_string}"
|
||||
)
|
||||
self._context.cursor.execute(steam_special_offer.udpate_string)
|
||||
|
||||
def delete_steam_special_offer(self, steam_special_offer: SteamSpecialOffer):
|
||||
self._logger.trace(
|
||||
__name__, f"Send SQL command: {steam_special_offer.delete_string}"
|
||||
)
|
||||
self._context.cursor.execute(steam_special_offer.delete_string)
|
@@ -1,63 +0,0 @@
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
from bot_data.model.user_warnings import UserWarnings
|
||||
from bot_graphql.abc.filter_abc import FilterABC
|
||||
|
||||
|
||||
class UserWarningFilter(FilterABC):
|
||||
def __init__(
|
||||
self,
|
||||
services: ServiceProviderABC,
|
||||
):
|
||||
FilterABC.__init__(self)
|
||||
|
||||
self._services = services
|
||||
|
||||
self._id = None
|
||||
self._user = None
|
||||
self._description = None
|
||||
self._author = None
|
||||
|
||||
def from_dict(self, values: dict):
|
||||
if "id" in values:
|
||||
self._id = int(values["id"])
|
||||
|
||||
if "user" in values:
|
||||
from bot_graphql.filter.user_filter import UserFilter
|
||||
|
||||
self._user: UserFilter = self._services.get_service(UserFilter)
|
||||
self._user.from_dict(values["user"])
|
||||
|
||||
if "description" in values:
|
||||
self._description = values["description"]
|
||||
|
||||
if "author" in values:
|
||||
from bot_graphql.filter.user_filter import UserFilter
|
||||
|
||||
self._author: UserFilter = self._services.get_service(UserFilter)
|
||||
self._author.from_dict(values["author"])
|
||||
|
||||
def filter(self, query: List[UserWarnings]) -> List[UserWarnings]:
|
||||
if self._id is not None:
|
||||
query = query.where(lambda x: x.id == self._id)
|
||||
|
||||
if self._user is not None:
|
||||
users = self._user.filter(query.select(lambda x: x.user)).select(
|
||||
lambda x: x.id
|
||||
)
|
||||
query = query.where(lambda x: x.id in users)
|
||||
|
||||
if self._description is not None:
|
||||
query = query.where(
|
||||
lambda x: x.description == self._description
|
||||
or self._description in x.description
|
||||
)
|
||||
|
||||
if self._author is not None:
|
||||
users = self._author.filter(query.select(lambda x: x.author)).select(
|
||||
lambda x: x.id
|
||||
)
|
||||
query = query.where(lambda x: x.id in users)
|
||||
|
||||
return query
|
@@ -1,34 +0,0 @@
|
||||
type UserWarning implements TableWithHistoryQuery {
|
||||
id: ID
|
||||
user: User
|
||||
description: String
|
||||
author: User
|
||||
|
||||
createdAt: String
|
||||
modifiedAt: String
|
||||
|
||||
history: [UserWarningHistory]
|
||||
}
|
||||
|
||||
type UserWarningHistory implements HistoryTableQuery {
|
||||
id: ID
|
||||
user: ID
|
||||
description: String
|
||||
author: ID
|
||||
|
||||
deleted: Boolean
|
||||
dateFrom: String
|
||||
dateTo: String
|
||||
}
|
||||
|
||||
input UserWarningFilter {
|
||||
id: ID
|
||||
user: UserFilter
|
||||
}
|
||||
|
||||
input UserWarningInput {
|
||||
id: ID
|
||||
user: ID
|
||||
description: String
|
||||
author: ID
|
||||
}
|
@@ -1,110 +0,0 @@
|
||||
from datetime import datetime
|
||||
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
|
||||
from bot_api.route.route import Route
|
||||
from bot_data.abc.level_repository_abc import LevelRepositoryABC
|
||||
from bot_data.abc.server_repository_abc import ServerRepositoryABC
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC
|
||||
from bot_data.model.user import User
|
||||
from bot_data.model.user_role_enum import UserRoleEnum
|
||||
from bot_graphql.abc.query_abc import QueryABC
|
||||
from modules.base.service.user_warnings_service import UserWarningsService
|
||||
from modules.level.service.level_service import LevelService
|
||||
from modules.permission.service.permission_service import PermissionService
|
||||
|
||||
|
||||
class UserMutation(QueryABC):
|
||||
def __init__(
|
||||
self,
|
||||
servers: ServerRepositoryABC,
|
||||
users: UserRepositoryABC,
|
||||
bot: DiscordBotServiceABC,
|
||||
db: DatabaseContextABC,
|
||||
permissions: PermissionService,
|
||||
levels: LevelRepositoryABC,
|
||||
level_service: LevelService,
|
||||
user_warnings: UserWarningsRepositoryABC,
|
||||
user_warning_service: UserWarningsService,
|
||||
):
|
||||
QueryABC.__init__(self, "UserMutation")
|
||||
|
||||
self._servers = servers
|
||||
self._users = users
|
||||
self._bot = bot
|
||||
self._db = db
|
||||
self._permissions = permissions
|
||||
self._levels = levels
|
||||
self._level_service = level_service
|
||||
self._user_warnings = user_warnings
|
||||
self._user_warning_service = user_warning_service
|
||||
|
||||
self.set_field("updateUser", self.resolve_update_user)
|
||||
|
||||
def resolve_update_user(self, *_, input: dict):
|
||||
user = self._users.get_user_by_id(input["id"])
|
||||
|
||||
auth_user = Route.get_user()
|
||||
member = self._bot.get_guild(user.server.discord_id).get_member(
|
||||
auth_user.users.where(lambda x: x.server.id == user.server.id)
|
||||
.single()
|
||||
.discord_id
|
||||
)
|
||||
if member.id != user.discord_id:
|
||||
self._can_user_mutate_data(user.server, UserRoleEnum.moderator)
|
||||
|
||||
new_xp = None
|
||||
if "levelId" in input:
|
||||
level = self._levels.get_level_by_id(input["levelId"])
|
||||
if user.level.id != level.id:
|
||||
new_xp = level.min_xp
|
||||
|
||||
if "userWarnings" in input:
|
||||
self._update_user_warning(user, input["userWarnings"])
|
||||
|
||||
user.xp = (
|
||||
new_xp
|
||||
if new_xp is not None
|
||||
else input["xp"]
|
||||
if "xp" in input
|
||||
else user.xp
|
||||
)
|
||||
|
||||
user.birthday = (
|
||||
datetime.strptime(input["birthday"], "%d.%m.%Y")
|
||||
if "birthday" in input
|
||||
else user.birthday
|
||||
)
|
||||
|
||||
self._users.update_user(user)
|
||||
self._db.save_changes()
|
||||
self._bot.loop.create_task(self._level_service.set_level(user))
|
||||
|
||||
user = self._users.get_user_by_id(input["id"])
|
||||
return user
|
||||
|
||||
def _update_user_warning(self, user: User, new_warnings: dict):
|
||||
old_warnings = self._user_warnings.get_user_warnings_by_user_id(user.id)
|
||||
for warning in old_warnings:
|
||||
if warning.id in [
|
||||
int(x["id"]) if "id" in x else None for x in new_warnings
|
||||
]:
|
||||
continue
|
||||
|
||||
self._user_warning_service.remove_warnings(warning.id)
|
||||
|
||||
for warning in new_warnings:
|
||||
if "id" in warning and int(warning["id"]) in old_warnings.select(
|
||||
lambda x: x.id
|
||||
):
|
||||
continue
|
||||
|
||||
member = self._bot.get_guild(user.server.discord_id).get_member(
|
||||
user.discord_id
|
||||
)
|
||||
author = self._users.get_user_by_id(int(warning["author"]))
|
||||
self._user_warning_service.add_warnings(
|
||||
member, warning["description"], author.discord_id
|
||||
)
|
@@ -1,11 +0,0 @@
|
||||
from bot_graphql.abc.history_query_abc import HistoryQueryABC
|
||||
|
||||
|
||||
class UserWarningHistoryQuery(HistoryQueryABC):
|
||||
def __init__(self):
|
||||
HistoryQueryABC.__init__(self, "UserWarning")
|
||||
|
||||
self.set_field("id", lambda x, *_: x.id)
|
||||
self.set_field("user", lambda x, *_: x.user)
|
||||
self.set_field("description", lambda x, *_: x.description)
|
||||
self.set_field("author", lambda x, *_: x.author)
|
@@ -1,19 +0,0 @@
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
|
||||
from bot_data.model.user_warnings_history import UserWarningsHistory
|
||||
from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC
|
||||
|
||||
|
||||
class UserWarningQuery(DataQueryWithHistoryABC):
|
||||
def __init__(
|
||||
self,
|
||||
db: DatabaseContextABC,
|
||||
):
|
||||
DataQueryWithHistoryABC.__init__(
|
||||
self, "UserWarning", "UserWarningsHistory", UserWarningsHistory, db
|
||||
)
|
||||
|
||||
self.set_field("id", lambda x, *_: x.id)
|
||||
self.set_field("user", lambda x, *_: x.user)
|
||||
self.set_field("description", lambda x, *_: x.description)
|
||||
self.set_field("author", lambda x, *_: x.author)
|
@@ -1,71 +0,0 @@
|
||||
import datetime
|
||||
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
from cpl_translation import TranslatePipe
|
||||
from discord.ext import tasks
|
||||
|
||||
from bot_core.abc.task_abc import TaskABC
|
||||
from bot_core.logging.task_logger import TaskLogger
|
||||
from bot_core.service.message_service import MessageService
|
||||
from bot_data.abc.user_repository_abc import UserRepositoryABC
|
||||
from bot_data.model.server_config import ServerConfig
|
||||
|
||||
|
||||
class BirthdayWatcher(TaskABC):
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
logger: TaskLogger,
|
||||
bot: DiscordBotServiceABC,
|
||||
db: DatabaseContextABC,
|
||||
users: UserRepositoryABC,
|
||||
message_service: MessageService,
|
||||
t: TranslatePipe,
|
||||
):
|
||||
TaskABC.__init__(self)
|
||||
|
||||
self._config = config
|
||||
self._logger = logger
|
||||
self._bot = bot
|
||||
self._db = db
|
||||
self._users = users
|
||||
self._message_service = message_service
|
||||
self._t = t
|
||||
|
||||
self.watch.start()
|
||||
|
||||
@tasks.loop(time=datetime.time(hour=8, minute=0))
|
||||
async def watch(self):
|
||||
self._logger.info(__name__, "Watching birthdays")
|
||||
try:
|
||||
today = datetime.date.today()
|
||||
users = self._users.get_users().where(lambda x: x.birthday is not None)
|
||||
for user in users:
|
||||
if user.birthday.day != today.day or user.birthday.month != today.month:
|
||||
continue
|
||||
|
||||
settings: ServerConfig = self._config.get_configuration(
|
||||
f"ServerConfig_{user.server.discord_id}"
|
||||
)
|
||||
|
||||
user.xp += settings.xp_for_birthday
|
||||
self._users.update_user(user)
|
||||
self._db.save_changes()
|
||||
|
||||
guild = self._bot.get_guild(user.server.discord_id)
|
||||
member = guild.get_member(user.discord_id)
|
||||
await self._message_service.send_channel_message(
|
||||
self._bot.get_channel(settings.notification_chat_id),
|
||||
self._t.transform("modules.base.user.birthday.has_birthday").format(
|
||||
member.mention
|
||||
),
|
||||
is_persistent=True,
|
||||
)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Watching birthdays failed", e)
|
||||
|
||||
@watch.before_loop
|
||||
async def wait(self):
|
||||
await self._wait_until_ready()
|
@@ -1,26 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
bot sh-edraft.de Discord bot
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Discord bot for customers of sh-edraft.de
|
||||
|
||||
:copyright: (c) 2022 - 2023 sh-edraft.de
|
||||
:license: MIT, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
__title__ = "modules.special_offers"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"ProjectSettings": {
|
||||
"Name": "steam-special-offers",
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "2",
|
||||
"Micro": "0"
|
||||
},
|
||||
"Author": "",
|
||||
"AuthorEmail": "",
|
||||
"Description": "",
|
||||
"LongDescription": "",
|
||||
"URL": "",
|
||||
"CopyrightDate": "",
|
||||
"CopyrightName": "",
|
||||
"LicenseName": "",
|
||||
"LicenseDescription": "",
|
||||
"Dependencies": [
|
||||
"cpl-core>=1.2.0"
|
||||
],
|
||||
"DevDependencies": [
|
||||
"cpl-cli>=1.2.0"
|
||||
],
|
||||
"PythonVersion": ">=3.10.4",
|
||||
"PythonPath": {
|
||||
"linux": ""
|
||||
},
|
||||
"Classifiers": []
|
||||
},
|
||||
"BuildSettings": {
|
||||
"ProjectType": "library",
|
||||
"SourcePath": "",
|
||||
"OutputPath": "../../dist",
|
||||
"Main": "steam_special_offers.main",
|
||||
"EntryPoint": "steam-special-offers",
|
||||
"IncludePackageData": false,
|
||||
"Included": [],
|
||||
"Excluded": [
|
||||
"*/__pycache__",
|
||||
"*/logs",
|
||||
"*/tests"
|
||||
],
|
||||
"PackageData": {},
|
||||
"ProjectReferences": []
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
from cpl_discord.service.discord_collection_abc import DiscordCollectionABC
|
||||
|
||||
from bot_core.abc.module_abc import ModuleABC
|
||||
from bot_core.abc.task_abc import TaskABC
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from modules.special_offers.steam_offer_watcher import SteamOfferWatcher
|
||||
|
||||
|
||||
class SteamSpecialOffersModule(ModuleABC):
|
||||
def __init__(self, dc: DiscordCollectionABC):
|
||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.steam_special_offers_module)
|
||||
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
pass
|
||||
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
services.add_singleton(TaskABC, SteamOfferWatcher)
|
||||
# commands
|
||||
# events
|
@@ -1,236 +0,0 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
|
||||
import bs4
|
||||
import discord
|
||||
import requests
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.database.context import DatabaseContextABC
|
||||
from cpl_discord.service import DiscordBotServiceABC
|
||||
from cpl_query.extension import List
|
||||
from cpl_translation import TranslatePipe
|
||||
from discord.ext import tasks
|
||||
|
||||
from bot_core.abc.task_abc import TaskABC
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
||||
from bot_core.logging.task_logger import TaskLogger
|
||||
from bot_core.service.message_service import MessageService
|
||||
from bot_data.abc.steam_special_offer_repository_abc import (
|
||||
SteamSpecialOfferRepositoryABC,
|
||||
)
|
||||
from bot_data.model.server_config import ServerConfig
|
||||
from bot_data.model.steam_special_offer import SteamSpecialOffer
|
||||
|
||||
|
||||
class SteamOfferWatcher(TaskABC):
|
||||
def __init__(
|
||||
self,
|
||||
config: ConfigurationABC,
|
||||
bot: DiscordBotServiceABC,
|
||||
logger: TaskLogger,
|
||||
db: DatabaseContextABC,
|
||||
offers: SteamSpecialOfferRepositoryABC,
|
||||
message_service: MessageService,
|
||||
t: TranslatePipe,
|
||||
):
|
||||
TaskABC.__init__(self)
|
||||
|
||||
self._config = config
|
||||
self._logger = logger
|
||||
self._db = db
|
||||
self._offers = offers
|
||||
self._bot = bot
|
||||
self._message_service = message_service
|
||||
self._t = t
|
||||
|
||||
self._is_new = False
|
||||
self._urls = {}
|
||||
self._image_urls = {}
|
||||
|
||||
self.watch.start()
|
||||
|
||||
@staticmethod
|
||||
def _get_max_count() -> int:
|
||||
count = 0
|
||||
result = requests.get(
|
||||
f"https://store.steampowered.com/search/results?specials=1"
|
||||
)
|
||||
soup = bs4.BeautifulSoup(result.text, "lxml")
|
||||
element = soup.find_all("div", {"class": "search_results_count"})
|
||||
if len(element) < 1:
|
||||
return count
|
||||
|
||||
count = int(element[0].contents[0].split(" ")[0].replace(",", ""))
|
||||
|
||||
return count
|
||||
|
||||
def _get_games_from_page(self, start: int, count: int) -> List[SteamSpecialOffer]:
|
||||
games = List(SteamSpecialOffer)
|
||||
result = requests.get(
|
||||
f"https://store.steampowered.com/search/results?query&start={start}&count={count}&force_infinite=1&specials=1"
|
||||
)
|
||||
soup = bs4.BeautifulSoup(result.text, "lxml")
|
||||
elements = soup.find_all("a", {"class": "search_result_row"})
|
||||
if len(elements) < 1:
|
||||
return games
|
||||
|
||||
for element in elements:
|
||||
name_element = element.find("span", {"class": "title"})
|
||||
original_price_element = element.find(
|
||||
"div", {"class": "discount_original_price"}
|
||||
)
|
||||
discount_element = element.find("div", {"class": "discount_pct"})
|
||||
discount_price_element = element.find(
|
||||
"div", {"class": "discount_final_price"}
|
||||
)
|
||||
|
||||
if (
|
||||
name_element is None
|
||||
or len(name_element.contents) < 1
|
||||
or original_price_element is None
|
||||
or len(original_price_element.contents) < 1
|
||||
or discount_element is None
|
||||
or len(discount_element.contents) < 1
|
||||
or discount_price_element is None
|
||||
or len(discount_price_element.contents) < 1
|
||||
):
|
||||
continue
|
||||
|
||||
name = name_element.contents[0].replace("'", "`").replace('"', "`")
|
||||
original_price = float(
|
||||
original_price_element.contents[0]
|
||||
.replace(" ", "")
|
||||
.replace("€", "")
|
||||
.replace(",", ".")
|
||||
)
|
||||
discount = int(discount_element.contents[0].replace("%", ""))
|
||||
discount_price = float(
|
||||
discount_price_element.contents[0]
|
||||
.replace(" ", "")
|
||||
.replace("€", "")
|
||||
.replace(",", ".")
|
||||
)
|
||||
games.add(SteamSpecialOffer(name, original_price, discount_price, discount))
|
||||
self._urls[name] = element.attrs["href"]
|
||||
self._image_urls[name] = (
|
||||
element.find("div", {"class": "search_capsule"})
|
||||
.find("img")
|
||||
.attrs["src"]
|
||||
)
|
||||
|
||||
return games
|
||||
|
||||
def _get_new_game_offers(self) -> List[SteamSpecialOffer]:
|
||||
new_offers = List(SteamSpecialOffer)
|
||||
|
||||
# sale_count = self._get_max_count() + 100
|
||||
sale_count = 500 # only look at first 500
|
||||
self._logger.debug(__name__, f"Get special offers from 0 to {sale_count}")
|
||||
for i in range(0, sale_count, 100):
|
||||
new_offers.extend(self._get_games_from_page(i, 100))
|
||||
|
||||
self._logger.debug(__name__, f"Got {new_offers.count()} offers")
|
||||
|
||||
return new_offers
|
||||
|
||||
async def _send_embed_for_offer(
|
||||
self, offer: SteamSpecialOffer, channel_id: int
|
||||
) -> discord.Embed:
|
||||
embed = discord.Embed(
|
||||
title=offer.name,
|
||||
url=self._urls[offer.name],
|
||||
color=int("ef9d0d", 16),
|
||||
timestamp=datetime.datetime.now(),
|
||||
)
|
||||
|
||||
embed.add_field(
|
||||
name=self._t.transform("modules.special_offers.price"),
|
||||
value=f"~~{offer.original_price}€~~",
|
||||
inline=True,
|
||||
)
|
||||
embed.add_field(
|
||||
name=self._t.transform("modules.special_offers.discount"),
|
||||
value=f"{offer.discount_pct}%",
|
||||
inline=True,
|
||||
)
|
||||
embed.add_field(
|
||||
name=self._t.transform("modules.special_offers.discount_price"),
|
||||
value=f"{offer.discount_price}€",
|
||||
inline=True,
|
||||
)
|
||||
|
||||
embed.set_image(url=self._image_urls[offer.name])
|
||||
|
||||
await self._message_service.send_channel_message(
|
||||
self._bot.get_channel(channel_id),
|
||||
embed,
|
||||
is_persistent=True,
|
||||
)
|
||||
|
||||
def _watch(self) -> List[SteamSpecialOffer]:
|
||||
self._is_new = self._offers.get_steam_special_offers().count() == 0
|
||||
new_offers = self._get_new_game_offers()
|
||||
new_offers_names = new_offers.select(lambda x: x.name).to_list()
|
||||
|
||||
old_offers = self._offers.get_steam_special_offers()
|
||||
old_offers_names = old_offers.select(lambda x: x.name).to_list()
|
||||
|
||||
offers_for_notifications = List(SteamSpecialOffer)
|
||||
|
||||
for offer in old_offers:
|
||||
offer: SteamSpecialOffer = offer
|
||||
if offer.name in new_offers_names:
|
||||
continue
|
||||
|
||||
self._offers.delete_steam_special_offer(offer)
|
||||
self._db.save_changes()
|
||||
|
||||
for offer in new_offers:
|
||||
if offer.name in old_offers_names:
|
||||
self._offers.update_steam_special_offer(offer)
|
||||
self._db.save_changes()
|
||||
continue
|
||||
|
||||
self._offers.add_steam_special_offer(offer)
|
||||
self._db.save_changes()
|
||||
offers_for_notifications.add(offer)
|
||||
|
||||
self._logger.trace(__name__, "Finished watching")
|
||||
return offers_for_notifications
|
||||
|
||||
@tasks.loop(time=datetime.time(hour=16, minute=30))
|
||||
async def watch(self):
|
||||
self._logger.info(__name__, "Watching steam special offers")
|
||||
try:
|
||||
offers_for_notifications = self._watch()
|
||||
self._logger.debug(
|
||||
__name__,
|
||||
f"Sending offer notifications for {offers_for_notifications.count()} offers",
|
||||
)
|
||||
if self._is_new:
|
||||
return
|
||||
for guild in self._bot.guilds:
|
||||
settings: ServerConfig = self._config.get_configuration(
|
||||
f"ServerConfig_{guild.id}"
|
||||
)
|
||||
if (
|
||||
not FeatureFlagsSettings.get_flag_from_dict(
|
||||
settings.feature_flags, FeatureFlagsEnum.steam_special_offers
|
||||
)
|
||||
or settings.game_offer_notification_chat_id is None
|
||||
):
|
||||
continue
|
||||
|
||||
for offer in offers_for_notifications:
|
||||
self._bot.loop.create_task(
|
||||
self._send_embed_for_offer(
|
||||
offer, settings.game_offer_notification_chat_id
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Steam offer watcher failed", e)
|
||||
|
||||
@watch.before_loop
|
||||
async def wait(self):
|
||||
await self._wait_until_ready()
|
@@ -17,7 +17,6 @@
|
||||
"permission": "src/modules/permission/permission.json",
|
||||
"technician": "src/modules/technician/technician.json",
|
||||
"short-role-name": "src/modules/short_role_name/short-role-name.json",
|
||||
"special-offers": "src/modules/special_offers/special-offers.json",
|
||||
"checks": "tools/checks/checks.json",
|
||||
"get-version": "tools/get_version/get-version.json",
|
||||
"post-build": "tools/post_build/post-build.json",
|
1
kdb-bot/docker
Submodule
1
kdb-bot/docker
Submodule
Submodule kdb-bot/docker added at 7ae4783874
@@ -15,7 +15,7 @@ __title__ = "bot"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -8,7 +8,6 @@ from cpl_discord.service import DiscordBotServiceABC, DiscordBotService
|
||||
from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings
|
||||
|
||||
from bot_api.api_thread import ApiThread
|
||||
from bot_core.abc.task_abc import TaskABC
|
||||
from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum
|
||||
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
||||
from bot_core.service.data_integrity_service import DataIntegrityService
|
||||
@@ -23,25 +22,15 @@ class Application(DiscordBotApplicationABC):
|
||||
|
||||
# cpl-core
|
||||
self._logger: LoggerABC = services.get_service(LoggerABC)
|
||||
self._data_integrity: DataIntegrityService = services.get_service(
|
||||
DataIntegrityService
|
||||
)
|
||||
self._data_integrity: DataIntegrityService = services.get_service(DataIntegrityService)
|
||||
# cpl-discord
|
||||
self._bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC)
|
||||
self._bot_settings: DiscordBotSettings = config.get_configuration(
|
||||
DiscordBotSettings
|
||||
)
|
||||
self._bot_settings: DiscordBotSettings = config.get_configuration(DiscordBotSettings)
|
||||
# cpl-translation
|
||||
self._translation: TranslationServiceABC = services.get_service(
|
||||
TranslationServiceABC
|
||||
)
|
||||
self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC)
|
||||
self._t: TranslatePipe = services.get_service(TranslatePipe)
|
||||
# internal stuff
|
||||
self._tasks = services.get_services(TaskABC)
|
||||
|
||||
self._feature_flags: FeatureFlagsSettings = config.get_configuration(
|
||||
FeatureFlagsSettings
|
||||
)
|
||||
self._feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
|
||||
|
||||
# api
|
||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||
@@ -50,9 +39,7 @@ class Application(DiscordBotApplicationABC):
|
||||
self._is_stopping = False
|
||||
|
||||
async def configure(self):
|
||||
self._translation.load_by_settings(
|
||||
self._configuration.get_configuration(TranslationSettings)
|
||||
)
|
||||
self._translation.load_by_settings(self._configuration.get_configuration(TranslationSettings))
|
||||
|
||||
async def main(self):
|
||||
try:
|
||||
@@ -68,9 +55,6 @@ class Application(DiscordBotApplicationABC):
|
||||
return
|
||||
|
||||
self._logger.info(__name__, f"Try to start {DiscordBotService.__name__}")
|
||||
for task in self._tasks:
|
||||
await self._bot.add_cog(task)
|
||||
|
||||
await self._bot.start_async()
|
||||
await self._bot.stop_async()
|
||||
except Exception as e:
|
||||
@@ -95,8 +79,4 @@ class Application(DiscordBotApplicationABC):
|
||||
Console.write_line()
|
||||
|
||||
def is_restart(self):
|
||||
return (
|
||||
True
|
||||
if self._configuration.get_configuration("IS_RESTART") == "true"
|
||||
else False
|
||||
)
|
||||
return True if self._configuration.get_configuration("IS_RESTART") == "true" else False
|
@@ -3,8 +3,8 @@
|
||||
"Name": "bot",
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "2",
|
||||
"Micro": "0"
|
||||
"Minor": "1",
|
||||
"Micro": "10"
|
||||
},
|
||||
"Author": "Sven Heidemann",
|
||||
"AuthorEmail": "sven.heidemann@sh-edraft.de",
|
||||
@@ -16,22 +16,22 @@
|
||||
"LicenseName": "MIT",
|
||||
"LicenseDescription": "MIT, see LICENSE for more details.",
|
||||
"Dependencies": [
|
||||
"cpl-core==2023.10.0",
|
||||
"cpl-core==2023.4.0.post5",
|
||||
"cpl-translation==2023.4.0.post1",
|
||||
"cpl-query==2023.10.0",
|
||||
"cpl-discord==2023.10.0.post1",
|
||||
"Flask==3.0.0",
|
||||
"Flask-Classful==0.16.0",
|
||||
"cpl-query==2023.4.0.post1",
|
||||
"cpl-discord==2023.4.0.post3",
|
||||
"Flask==2.3.2",
|
||||
"Flask-Classful==0.14.2",
|
||||
"Flask-Cors==4.0.0",
|
||||
"PyJWT==2.8.0",
|
||||
"waitress==2.1.2",
|
||||
"Flask-SocketIO==5.3.6",
|
||||
"Flask-SocketIO==5.3.4",
|
||||
"eventlet==0.33.3",
|
||||
"requests-oauthlib==1.3.1",
|
||||
"icmplib==3.0.4",
|
||||
"icmplib==3.0.3",
|
||||
"ariadne==0.20.1",
|
||||
"cryptography==41.0.4",
|
||||
"discord==2.3.2"
|
||||
"cryptography==41.0.2",
|
||||
"discord>=2.3.2"
|
||||
],
|
||||
"DevDependencies": [
|
||||
"cpl-cli==2023.4.0.post3",
|
||||
@@ -69,7 +69,6 @@
|
||||
"../modules/level/level.json",
|
||||
"../modules/permission/permission.json",
|
||||
"../modules/short_role_name/short-role-name.json",
|
||||
"../modules/special_offers/special-offers.json",
|
||||
"../modules/technician/technician.json"
|
||||
]
|
||||
}
|
1
kdb-bot/src/bot/config
Submodule
1
kdb-bot/src/bot/config
Submodule
Submodule kdb-bot/src/bot/config added at 23eafb2e21
@@ -15,7 +15,7 @@ __title__ = "bot.extension"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -13,6 +13,4 @@ class InitBotExtension(ApplicationExtensionABC):
|
||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
settings = config.get_configuration(TechnicianConfig)
|
||||
|
||||
bot: DiscordBotServiceABC = services.get_service(
|
||||
DiscordBotServiceABC, max_messages=settings.cache_max_messages
|
||||
)
|
||||
bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC, max_messages=settings.cache_max_messages)
|
@@ -14,7 +14,6 @@ from modules.database.database_module import DatabaseModule
|
||||
from modules.level.level_module import LevelModule
|
||||
from modules.permission.permission_module import PermissionModule
|
||||
from modules.short_role_name.short_role_name_module import ShortRoleNameModule
|
||||
from modules.special_offers.special_offers_module import SteamSpecialOffersModule
|
||||
from modules.technician.technician_module import TechnicianModule
|
||||
|
||||
|
||||
@@ -38,7 +37,6 @@ class ModuleList:
|
||||
TechnicianModule,
|
||||
AchievementsModule,
|
||||
ShortRoleNameModule,
|
||||
SteamSpecialOffersModule,
|
||||
# has to be last!
|
||||
BootLogModule,
|
||||
CoreExtensionModule,
|
@@ -16,7 +16,6 @@ from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
|
||||
from bot_core.logging.command_logger import CommandLogger
|
||||
from bot_core.logging.database_logger import DatabaseLogger
|
||||
from bot_core.logging.message_logger import MessageLogger
|
||||
from bot_core.logging.task_logger import TaskLogger
|
||||
from bot_data.db_context import DBContext
|
||||
|
||||
|
||||
@@ -44,15 +43,12 @@ class Startup(StartupABC):
|
||||
services.add_singleton(CustomFileLoggerABC, CommandLogger)
|
||||
services.add_singleton(CustomFileLoggerABC, DatabaseLogger)
|
||||
services.add_singleton(CustomFileLoggerABC, MessageLogger)
|
||||
services.add_singleton(CustomFileLoggerABC, TaskLogger)
|
||||
|
||||
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||
services.add_singleton(CustomFileLoggerABC, ApiLogger)
|
||||
|
||||
services.add_translation()
|
||||
services.add_db_context(
|
||||
DBContext, self._config.get_configuration(DatabaseSettings)
|
||||
)
|
||||
services.add_db_context(DBContext, self._config.get_configuration(DatabaseSettings))
|
||||
|
||||
provider = services.build_service_provider()
|
||||
# instantiate custom logger
|
@@ -9,13 +9,9 @@ class StartupDiscordExtension(StartupExtensionABC):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
pass
|
||||
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
services.add_discord()
|
||||
dcc = get_discord_collection(services)
|
58
kdb-bot/src/bot/startup_migration_extension.py
Normal file
58
kdb-bot/src/bot/startup_migration_extension.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from cpl_core.application import StartupExtensionABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.dependency_injection import ServiceCollectionABC
|
||||
from cpl_core.environment import ApplicationEnvironmentABC
|
||||
|
||||
from bot_data.abc.migration_abc import MigrationABC
|
||||
from bot_data.migration.achievements_migration import AchievementsMigration
|
||||
from bot_data.migration.api_key_migration import ApiKeyMigration
|
||||
from bot_data.migration.api_migration import ApiMigration
|
||||
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
|
||||
from bot_data.migration.auto_role_migration import AutoRoleMigration
|
||||
from bot_data.migration.config_feature_flags_migration import ConfigFeatureFlagsMigration
|
||||
from bot_data.migration.config_migration import ConfigMigration
|
||||
from bot_data.migration.db_history_migration import DBHistoryMigration
|
||||
from bot_data.migration.default_role_migration import DefaultRoleMigration
|
||||
from bot_data.migration.fix_updates_migration import FixUpdatesMigration
|
||||
from bot_data.migration.initial_migration import InitialMigration
|
||||
from bot_data.migration.level_migration import LevelMigration
|
||||
from bot_data.migration.remove_stats_migration import RemoveStatsMigration
|
||||
from bot_data.migration.short_role_name_migration import ShortRoleNameMigration
|
||||
from bot_data.migration.short_role_name_only_highest_migration import ShortRoleNameOnlyHighestMigration
|
||||
from bot_data.migration.stats_migration import StatsMigration
|
||||
from bot_data.migration.user_joined_game_server_migration import UserJoinedGameServerMigration
|
||||
from bot_data.migration.user_message_count_per_hour_migration import (
|
||||
UserMessageCountPerHourMigration,
|
||||
)
|
||||
from bot_data.migration.user_warning_migration import UserWarningMigration
|
||||
from bot_data.service.migration_service import MigrationService
|
||||
|
||||
|
||||
class StartupMigrationExtension(StartupExtensionABC):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
pass
|
||||
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
services.add_transient(MigrationService)
|
||||
services.add_transient(MigrationABC, InitialMigration)
|
||||
services.add_transient(MigrationABC, AutoRoleMigration) # 03.10.2022 #54 - 0.2.2
|
||||
services.add_transient(MigrationABC, ApiMigration) # 15.10.2022 #70 - 0.3.0
|
||||
services.add_transient(MigrationABC, LevelMigration) # 06.11.2022 #25 - 0.3.0
|
||||
services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0
|
||||
services.add_transient(MigrationABC, AutoRoleFix1Migration) # 30.12.2022 #151 - 0.3.0
|
||||
services.add_transient(MigrationABC, UserMessageCountPerHourMigration) # 11.01.2023 #168 - 0.3.1
|
||||
services.add_transient(MigrationABC, ApiKeyMigration) # 09.02.2023 #162 - 1.0.0
|
||||
services.add_transient(MigrationABC, UserJoinedGameServerMigration) # 12.02.2023 #181 - 1.0.0
|
||||
services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0
|
||||
services.add_transient(MigrationABC, UserWarningMigration) # 21.02.2023 #35 - 1.0.0
|
||||
services.add_transient(MigrationABC, DBHistoryMigration) # 06.03.2023 #246 - 1.0.0
|
||||
services.add_transient(MigrationABC, AchievementsMigration) # 14.06.2023 #268 - 1.1.0
|
||||
services.add_transient(MigrationABC, ConfigMigration) # 19.07.2023 #127 - 1.1.0
|
||||
services.add_transient(MigrationABC, ConfigFeatureFlagsMigration) # 15.08.2023 #334 - 1.1.0
|
||||
services.add_transient(MigrationABC, DefaultRoleMigration) # 24.09.2023 #360 - 1.1.3
|
||||
services.add_transient(MigrationABC, ShortRoleNameMigration) # 28.09.2023 #378 - 1.1.7
|
||||
services.add_transient(MigrationABC, FixUpdatesMigration) # 28.09.2023 #378 - 1.1.7
|
||||
services.add_transient(MigrationABC, ShortRoleNameOnlyHighestMigration) # 02.10.2023 #391 - 1.1.9
|
@@ -18,15 +18,11 @@ class StartupModuleExtension(StartupExtensionABC):
|
||||
|
||||
self._modules = ModuleList.get_modules()
|
||||
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
self._config = config
|
||||
self._feature_flags = config.get_configuration(FeatureFlagsSettings)
|
||||
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
provider = services.build_service_provider()
|
||||
dc_collection: DiscordCollectionABC = provider.get_service(DiscordCollectionABC)
|
||||
|
@@ -14,38 +14,26 @@ class StartupSettingsExtension(StartupExtensionABC):
|
||||
def __init__(self):
|
||||
self._start_time = datetime.now()
|
||||
|
||||
def configure_configuration(
|
||||
self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_configuration(self, configuration: ConfigurationABC, environment: ApplicationEnvironmentABC):
|
||||
# this shit has to be done here because we need settings in subsequent startup extensions
|
||||
environment.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
||||
configuration.add_environment_variables("KDB_")
|
||||
configuration.add_environment_variables("DISCORD_")
|
||||
|
||||
configuration.add_json_file(f"config/appsettings.json", optional=False)
|
||||
configuration.add_json_file(
|
||||
f"config/appsettings.{environment.environment_name}.json", optional=True
|
||||
)
|
||||
configuration.add_json_file(
|
||||
f"config/appsettings.{environment.host_name}.json", optional=True
|
||||
)
|
||||
configuration.add_json_file(f"config/appsettings.{environment.environment_name}.json", optional=True)
|
||||
configuration.add_json_file(f"config/appsettings.{environment.host_name}.json", optional=True)
|
||||
# load feature-flags
|
||||
configuration.add_json_file(f"config/feature-flags.json", optional=False)
|
||||
configuration.add_json_file(
|
||||
f"config/feature-flags.{environment.environment_name}.json", optional=True
|
||||
)
|
||||
configuration.add_json_file(
|
||||
f"config/feature-flags.{environment.host_name}.json", optional=True
|
||||
)
|
||||
configuration.add_json_file(f"config/feature-flags.{environment.environment_name}.json", optional=True)
|
||||
configuration.add_json_file(f"config/feature-flags.{environment.host_name}.json", optional=True)
|
||||
|
||||
configuration.add_configuration("Startup_StartTime", str(self._start_time))
|
||||
self._configure_settings_with_sub_settings(
|
||||
configuration, BotLoggingSettings, lambda x: x.files, lambda x: x.key
|
||||
)
|
||||
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@@ -57,6 +45,4 @@ class StartupSettingsExtension(StartupExtensionABC):
|
||||
return
|
||||
|
||||
for sub_settings in list_atr(settings):
|
||||
config.add_configuration(
|
||||
f"{type(sub_settings).__name__}_{atr(sub_settings)}", sub_settings
|
||||
)
|
||||
config.add_configuration(f"{type(sub_settings).__name__}_{atr(sub_settings)}", sub_settings)
|
@@ -94,11 +94,6 @@
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"special_offers": {
|
||||
"price": "Preis",
|
||||
"discount": "Rabatt",
|
||||
"discount_price": "Neuer Preis"
|
||||
},
|
||||
"achievements": {
|
||||
"commands": {
|
||||
"check": "Alles klar, ich schaue eben nach... nom nom"
|
||||
@@ -234,11 +229,6 @@
|
||||
"success": "Verlinkung wurde entfernt :D"
|
||||
},
|
||||
"user": {
|
||||
"birthday": {
|
||||
"has_birthday": "Alles Gute zum Geburtag {} :D",
|
||||
"success": "Dein Geburtstag wurde eingetragen.",
|
||||
"success_team": "{} hat seinen Geburtstag eingetragen: {}"
|
||||
},
|
||||
"add": {
|
||||
"xp": "Die {} von {} wurden um {} erhöht"
|
||||
},
|
@@ -15,7 +15,7 @@ __title__ = "bot_api"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.abc"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -40,15 +40,11 @@ class AuthServiceABC(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_filtered_auth_users_async(
|
||||
self, criteria: AuthUserSelectCriteria
|
||||
) -> AuthUserFilteredResultDTO:
|
||||
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_auth_user_by_email_async(
|
||||
self, email: str, with_password: bool = False
|
||||
) -> AuthUserDTO:
|
||||
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
@@ -3,9 +3,7 @@ from abc import ABC, abstractmethod
|
||||
|
||||
class SelectCriteriaABC(ABC):
|
||||
@abstractmethod
|
||||
def __init__(
|
||||
self, page_index: int, page_size: int, sort_direction: str, sort_column: str
|
||||
):
|
||||
def __init__(self, page_index: int, page_size: int, sort_direction: str, sort_column: str):
|
||||
self.page_index = page_index
|
||||
self.page_size = page_size
|
||||
self.sort_direction = sort_direction
|
@@ -57,9 +57,7 @@ class Api(Flask):
|
||||
# Added async_mode see link below
|
||||
# https://github.com/miguelgrinberg/Flask-SocketIO/discussions/1849
|
||||
# https://stackoverflow.com/questions/39370848/flask-socket-io-sometimes-client-calls-freeze-the-server
|
||||
self._socketio = SocketIO(
|
||||
self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet"
|
||||
)
|
||||
self._socketio = SocketIO(self, cors_allowed_origins="*", path="/api/socket.io", async_mode="eventlet")
|
||||
self._socketio.on_event("connect", self.on_connect)
|
||||
self._socketio.on_event("disconnect", self.on_disconnect)
|
||||
|
||||
@@ -145,26 +143,19 @@ class Api(Flask):
|
||||
data = request.get_data()
|
||||
data = "" if len(data) == 0 else str(data.decode(encoding="utf-8"))
|
||||
|
||||
text = textwrap.dedent(
|
||||
f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}"
|
||||
)
|
||||
text = textwrap.dedent(f"Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}")
|
||||
self._logger.trace(__name__, text)
|
||||
|
||||
return response
|
||||
|
||||
def start(self):
|
||||
self._logger.info(
|
||||
__name__,
|
||||
f"Starting API {self._api_settings.host}:{self._api_settings.port}",
|
||||
)
|
||||
self._logger.info(__name__, f"Starting API {self._api_settings.host}:{self._api_settings.port}")
|
||||
self._register_routes()
|
||||
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
|
||||
# from waitress import serve
|
||||
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
|
||||
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
|
||||
self._socket = eventlet.listen(
|
||||
(self._api_settings.host, self._api_settings.port)
|
||||
)
|
||||
self._socket = eventlet.listen((self._api_settings.host, self._api_settings.port))
|
||||
wsgi.server(self._socket, self, log_output=False)
|
||||
|
||||
def stop(self):
|
@@ -26,21 +26,15 @@ class ApiModule(ModuleABC):
|
||||
def __init__(self, dc: DiscordCollectionABC):
|
||||
ModuleABC.__init__(self, dc, FeatureFlagsEnum.api_module)
|
||||
|
||||
def configure_configuration(
|
||||
self, config: ConfigurationABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC):
|
||||
cwd = env.working_directory
|
||||
env.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
|
||||
config.add_json_file(f"config/apisettings.json", optional=False)
|
||||
config.add_json_file(
|
||||
f"config/apisettings.{env.environment_name}.json", optional=True
|
||||
)
|
||||
config.add_json_file(f"config/apisettings.{env.environment_name}.json", optional=True)
|
||||
config.add_json_file(f"config/apisettings.{env.host_name}.json", optional=True)
|
||||
env.set_working_directory(cwd)
|
||||
|
||||
def configure_services(
|
||||
self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC
|
||||
):
|
||||
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC):
|
||||
services.add_singleton(EMailClientABC, EMailClient)
|
||||
|
||||
services.add_singleton(ApiThread)
|
||||
@@ -54,4 +48,4 @@ class ApiModule(ModuleABC):
|
||||
services.add_transient(GraphQLController)
|
||||
|
||||
# cpl-discord
|
||||
services.add_transient(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
||||
self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)
|
@@ -12,9 +12,7 @@ class AppApiExtension(ApplicationExtensionABC):
|
||||
ApplicationExtensionABC.__init__(self)
|
||||
|
||||
async def run(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||
feature_flags: FeatureFlagsSettings = config.get_configuration(
|
||||
FeatureFlagsSettings
|
||||
)
|
||||
feature_flags: FeatureFlagsSettings = config.get_configuration(FeatureFlagsSettings)
|
||||
if not feature_flags.get_flag(FeatureFlagsEnum.api_module):
|
||||
return
|
||||
|
@@ -3,8 +3,8 @@
|
||||
"Name": "bot-api",
|
||||
"Version": {
|
||||
"Major": "1",
|
||||
"Minor": "2",
|
||||
"Micro": "0"
|
||||
"Minor": "1",
|
||||
"Micro": "10"
|
||||
},
|
||||
"Author": "",
|
||||
"AuthorEmail": "",
|
1
kdb-bot/src/bot_api/config
Submodule
1
kdb-bot/src/bot_api/config
Submodule
Submodule kdb-bot/src/bot_api/config added at b6ffed4da1
@@ -15,7 +15,7 @@ __title__ = "bot_api.configuration"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -16,9 +16,7 @@ class AuthenticationSettings(ConfigurationModelABC):
|
||||
self._issuer = "" if issuer is None else issuer
|
||||
self._audience = "" if audience is None else audience
|
||||
self._token_expire_time = 0 if token_expire_time is None else token_expire_time
|
||||
self._refresh_token_expire_time = (
|
||||
0 if refresh_token_expire_time is None else refresh_token_expire_time
|
||||
)
|
||||
self._refresh_token_expire_time = 0 if refresh_token_expire_time is None else refresh_token_expire_time
|
||||
|
||||
@property
|
||||
def secret_key(self) -> str:
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.controller"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -70,9 +70,7 @@ class AuthController:
|
||||
|
||||
@Route.post(f"{BasePath}/register")
|
||||
async def register(self):
|
||||
dto: AuthUserDTO = JSONProcessor.process(
|
||||
AuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
self._auth_service.add_auth_user(dto)
|
||||
return "", 200
|
||||
|
||||
@@ -83,9 +81,7 @@ class AuthController:
|
||||
|
||||
@Route.post(f"{BasePath}/login")
|
||||
async def login(self) -> Response:
|
||||
dto: AuthUserDTO = JSONProcessor.process(
|
||||
AuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
result = await self._auth_service.login_async(dto)
|
||||
return jsonify(result.to_dict())
|
||||
|
||||
@@ -114,52 +110,40 @@ class AuthController:
|
||||
|
||||
@Route.post(f"{BasePath}/reset-password")
|
||||
async def reset_password(self):
|
||||
dto: ResetPasswordDTO = JSONProcessor.process(
|
||||
ResetPasswordDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: ResetPasswordDTO = JSONProcessor.process(ResetPasswordDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.reset_password_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/update-user")
|
||||
@Route.authorize
|
||||
async def update_user(self):
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(
|
||||
UpdateAuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.update_user_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/update-user-as-admin")
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def update_user_as_admin(self):
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(
|
||||
UpdateAuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: UpdateAuthUserDTO = JSONProcessor.process(UpdateAuthUserDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.update_user_as_admin_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/refresh")
|
||||
async def refresh(self) -> Response:
|
||||
dto: TokenDTO = JSONProcessor.process(
|
||||
TokenDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
|
||||
result = await self._auth_service.refresh_async(dto)
|
||||
return jsonify(result.to_dict())
|
||||
|
||||
@Route.post(f"{BasePath}/revoke")
|
||||
async def revoke(self):
|
||||
dto: TokenDTO = JSONProcessor.process(
|
||||
TokenDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.revoke_async(dto)
|
||||
return "", 200
|
||||
|
||||
@Route.post(f"{BasePath}/delete-user")
|
||||
@Route.authorize(role=AuthRoleEnum.admin)
|
||||
async def delete_user(self):
|
||||
dto: AuthUserDTO = JSONProcessor.process(
|
||||
AuthUserDTO, request.get_json(force=True, silent=True)
|
||||
)
|
||||
dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True))
|
||||
await self._auth_service.delete_auth_user_async(dto)
|
||||
return "", 200
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.event"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.exception"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -13,9 +13,7 @@ class AuthUserSelectCriteria(SelectCriteriaABC):
|
||||
email: str,
|
||||
auth_role: int,
|
||||
):
|
||||
SelectCriteriaABC.__init__(
|
||||
self, page_index, page_size, sort_direction, sort_column
|
||||
)
|
||||
SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column)
|
||||
|
||||
self.first_name = first_name
|
||||
self.last_name = last_name
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.filter.discord"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -10,8 +10,6 @@ class ServerSelectCriteria(SelectCriteriaABC):
|
||||
sort_column: str,
|
||||
name: str,
|
||||
):
|
||||
SelectCriteriaABC.__init__(
|
||||
self, page_index, page_size, sort_direction, sort_column
|
||||
)
|
||||
SelectCriteriaABC.__init__(self, page_index, page_size, sort_direction, sort_column)
|
||||
|
||||
self.name = name
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.logging"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.model"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.model.discord"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -11,9 +11,7 @@ class ErrorDTO(DtoABC):
|
||||
def __init__(self, error_code: Optional[ServiceErrorCode], message: str):
|
||||
DtoABC.__init__(self)
|
||||
|
||||
self._error_code = (
|
||||
ServiceErrorCode.Unknown if error_code is None else error_code
|
||||
)
|
||||
self._error_code = ServiceErrorCode.Unknown if error_code is None else error_code
|
||||
self._message = message
|
||||
|
||||
@property
|
@@ -27,8 +27,4 @@ class TokenDTO(DtoABC):
|
||||
self._first_login = values["firstLogin"]
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"token": self._token,
|
||||
"refreshToken": self._refresh_token,
|
||||
"firstLogin": self._first_login,
|
||||
}
|
||||
return {"token": self._token, "refreshToken": self._refresh_token, "firstLogin": self._first_login}
|
@@ -34,9 +34,7 @@ class UpdateAuthUserDTO(DtoABC):
|
||||
def from_dict(self, values: dict):
|
||||
self._auth_user = AuthUserDTO().from_dict(values["authUser"])
|
||||
self._new_auth_user = AuthUserDTO().from_dict(values["newAuthUser"])
|
||||
self._change_password = (
|
||||
False if "changePassword" not in values else bool(values["changePassword"])
|
||||
)
|
||||
self._change_password = False if "changePassword" not in values else bool(values["changePassword"])
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.route"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports:
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -25,12 +25,7 @@ class Route:
|
||||
|
||||
@classmethod
|
||||
@ServiceProviderABC.inject
|
||||
def init_authorize(
|
||||
cls,
|
||||
env: ApplicationEnvironmentABC,
|
||||
auth_users: AuthUserRepositoryABC,
|
||||
auth: AuthServiceABC,
|
||||
):
|
||||
def init_authorize(cls, env: ApplicationEnvironmentABC, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC):
|
||||
cls._auth_users = auth_users
|
||||
cls._auth = auth
|
||||
cls._env = env.environment_name
|
||||
@@ -57,17 +52,9 @@ class Route:
|
||||
return user
|
||||
|
||||
@classmethod
|
||||
def authorize(
|
||||
cls,
|
||||
f: Callable = None,
|
||||
role: AuthRoleEnum = None,
|
||||
skip_in_dev=False,
|
||||
by_api_key=False,
|
||||
):
|
||||
def authorize(cls, f: Callable = None, role: AuthRoleEnum = None, skip_in_dev=False, by_api_key=False):
|
||||
if f is None:
|
||||
return functools.partial(
|
||||
cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key
|
||||
)
|
||||
return functools.partial(cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key)
|
||||
|
||||
@wraps(f)
|
||||
async def decorator(*args, **kwargs):
|
||||
@@ -78,9 +65,7 @@ class Route:
|
||||
api_key = None
|
||||
if "Authorization" in request.headers:
|
||||
if " " not in request.headers.get("Authorization"):
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"Token not set"
|
||||
)
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set")
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
@@ -102,9 +87,7 @@ class Route:
|
||||
return jsonify(e), 500
|
||||
|
||||
if not valid:
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"API-Key invalid"
|
||||
)
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"API-Key invalid")
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
@@ -116,9 +99,7 @@ class Route:
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
if cls._auth_users is None or cls._auth is None:
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"Authorize is not initialized"
|
||||
)
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Authorize is not initialized")
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
@@ -140,9 +121,7 @@ class Route:
|
||||
return jsonify(error.to_dict()), 401
|
||||
|
||||
if role is not None and user.auth_role.value < role.value:
|
||||
ex = ServiceException(
|
||||
ServiceErrorCode.Unauthorized, f"Role {role} required"
|
||||
)
|
||||
ex = ServiceException(ServiceErrorCode.Unauthorized, f"Role {role} required")
|
||||
error = ErrorDTO(ex.error_code, ex.message)
|
||||
return jsonify(error.to_dict()), 403
|
||||
|
@@ -15,7 +15,7 @@ __title__ = "bot_api.service"
|
||||
__author__ = "Sven Heidemann"
|
||||
__license__ = "MIT"
|
||||
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
|
||||
__version__ = "1.2.0"
|
||||
__version__ = "1.1.10"
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -23,4 +23,4 @@ from collections import namedtuple
|
||||
# imports
|
||||
|
||||
VersionInfo = namedtuple("VersionInfo", "major minor micro")
|
||||
version_info = VersionInfo(major="1", minor="2", micro="0")
|
||||
version_info = VersionInfo(major="1", minor="1", micro="10")
|
@@ -90,9 +90,7 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
def _get_api_key_str(self, api_key: ApiKey) -> str:
|
||||
return hashlib.sha256(
|
||||
f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode(
|
||||
"utf-8"
|
||||
)
|
||||
f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode("utf-8")
|
||||
).hexdigest()
|
||||
|
||||
def generate_token(self, user: AuthUser) -> str:
|
||||
@@ -101,8 +99,7 @@ class AuthService(AuthServiceABC):
|
||||
"user_id": user.id,
|
||||
"email": user.email,
|
||||
"role": user.auth_role.value,
|
||||
"exp": datetime.now(tz=timezone.utc)
|
||||
+ timedelta(days=self._auth_settings.token_expire_time),
|
||||
"exp": datetime.now(tz=timezone.utc) + timedelta(days=self._auth_settings.token_expire_time),
|
||||
"iss": self._auth_settings.issuer,
|
||||
"aud": self._auth_settings.audience,
|
||||
},
|
||||
@@ -158,9 +155,7 @@ class AuthService(AuthServiceABC):
|
||||
def _create_and_save_refresh_token(self, user: AuthUser) -> str:
|
||||
token = str(uuid.uuid4())
|
||||
user.refresh_token = token
|
||||
user.refresh_token_expire_time = datetime.now() + timedelta(
|
||||
days=self._auth_settings.refresh_token_expire_time
|
||||
)
|
||||
user.refresh_token_expire_time = datetime.now() + timedelta(days=self._auth_settings.refresh_token_expire_time)
|
||||
self._auth_users.update_auth_user(user)
|
||||
self._db.save_changes()
|
||||
return token
|
||||
@@ -193,12 +188,8 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
self._send_link_mail(
|
||||
user.email,
|
||||
self._t.transform("api.auth.confirmation.subject").format(
|
||||
user.first_name, user.last_name
|
||||
),
|
||||
self._t.transform("api.auth.confirmation.message").format(
|
||||
url, user.confirmation_id
|
||||
),
|
||||
self._t.transform("api.auth.confirmation.subject").format(user.first_name, user.last_name),
|
||||
self._t.transform("api.auth.confirmation.message").format(url, user.confirmation_id),
|
||||
)
|
||||
|
||||
def _send_forgot_password_id_to_user(self, user: AuthUser):
|
||||
@@ -208,38 +199,28 @@ class AuthService(AuthServiceABC):
|
||||
|
||||
self._send_link_mail(
|
||||
user.email,
|
||||
self._t.transform("api.auth.forgot_password.subject").format(
|
||||
user.first_name, user.last_name
|
||||
),
|
||||
self._t.transform("api.auth.forgot_password.message").format(
|
||||
url, user.forgot_password_id
|
||||
),
|
||||
self._t.transform("api.auth.forgot_password.subject").format(user.first_name, user.last_name),
|
||||
self._t.transform("api.auth.forgot_password.message").format(url, user.forgot_password_id),
|
||||
)
|
||||
|
||||
async def get_all_auth_users_async(self) -> List[AuthUserDTO]:
|
||||
result = self._auth_users.get_all_auth_users().select(lambda x: AUT.to_dto(x))
|
||||
return List(AuthUserDTO, result)
|
||||
|
||||
async def get_filtered_auth_users_async(
|
||||
self, criteria: AuthUserSelectCriteria
|
||||
) -> AuthUserFilteredResultDTO:
|
||||
async def get_filtered_auth_users_async(self, criteria: AuthUserSelectCriteria) -> AuthUserFilteredResultDTO:
|
||||
users = self._auth_users.get_filtered_auth_users(criteria)
|
||||
result = users.result.select(lambda x: AUT.to_dto(x))
|
||||
|
||||
return AuthUserFilteredResultDTO(List(AuthUserDTO, result), users.total_count)
|
||||
|
||||
async def get_auth_user_by_email_async(
|
||||
self, email: str, with_password: bool = False
|
||||
) -> AuthUserDTO:
|
||||
async def get_auth_user_by_email_async(self, email: str, with_password: bool = False) -> AuthUserDTO:
|
||||
try:
|
||||
# todo: check if logged in user is admin then send mail
|
||||
user = self._auth_users.get_auth_user_by_email(email)
|
||||
return AUT.to_dto(user, password=user.password if with_password else None)
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"AuthUser not found", e)
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, f"User not found {email}"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User not found {email}")
|
||||
|
||||
async def find_auth_user_by_email_async(self, email: str) -> Optional[AuthUser]:
|
||||
user = self._auth_users.find_auth_user_by_email(email)
|
||||
@@ -257,22 +238,16 @@ class AuthService(AuthServiceABC):
|
||||
user.password_salt = uuid.uuid4()
|
||||
user.password = self._hash_sha256(user_dto.password, user.password_salt)
|
||||
if not self._is_email_valid(user.email):
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, "Invalid E-Mail address"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Invalid E-Mail address")
|
||||
|
||||
try:
|
||||
user.confirmation_id = uuid.uuid4()
|
||||
self._auth_users.add_auth_user(user)
|
||||
self._send_confirmation_id_to_user(user)
|
||||
self._db.save_changes()
|
||||
self._logger.info(
|
||||
__name__, f"Added auth user with E-Mail: {user_dto.email}"
|
||||
)
|
||||
self._logger.info(__name__, f"Added auth user with E-Mail: {user_dto.email}")
|
||||
except Exception as e:
|
||||
self._logger.error(
|
||||
__name__, f"Cannot add user with E-Mail {user_dto.email}", e
|
||||
)
|
||||
self._logger.error(__name__, f"Cannot add user with E-Mail {user_dto.email}", e)
|
||||
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||
|
||||
async def add_auth_user_by_oauth_async(self, dto: OAuthDTO):
|
||||
@@ -288,20 +263,14 @@ class AuthService(AuthServiceABC):
|
||||
db_user.first_name = dto.user.first_name
|
||||
db_user.last_name = dto.user.last_name
|
||||
db_user.password_salt = uuid.uuid4()
|
||||
db_user.password = self._hash_sha256(
|
||||
dto.user.password, db_user.password_salt
|
||||
)
|
||||
db_user.password = self._hash_sha256(dto.user.password, db_user.password_salt)
|
||||
db_user.oauth_id = None
|
||||
db_user.confirmation_id = uuid.uuid4()
|
||||
self._send_confirmation_id_to_user(db_user)
|
||||
self._auth_users.update_auth_user(db_user)
|
||||
self._logger.info(
|
||||
__name__, f"Added auth user with E-Mail: {dto.user.email}"
|
||||
)
|
||||
self._logger.info(__name__, f"Added auth user with E-Mail: {dto.user.email}")
|
||||
except Exception as e:
|
||||
self._logger.error(
|
||||
__name__, f"Cannot add user with E-Mail {dto.user.email}", e
|
||||
)
|
||||
self._logger.error(__name__, f"Cannot add user with E-Mail {dto.user.email}", e)
|
||||
raise ServiceException(ServiceErrorCode.UnableToAdd, "Invalid E-Mail")
|
||||
|
||||
self._db.save_changes()
|
||||
@@ -311,16 +280,14 @@ class AuthService(AuthServiceABC):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||
|
||||
if update_user_dto.auth_user is None:
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, f"Existing user is empty"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Existing user is empty")
|
||||
|
||||
if update_user_dto.new_auth_user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
|
||||
|
||||
if not self._is_email_valid(
|
||||
update_user_dto.auth_user.email
|
||||
) or not self._is_email_valid(update_user_dto.new_auth_user.email):
|
||||
if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(
|
||||
update_user_dto.new_auth_user.email
|
||||
):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
|
||||
|
||||
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
||||
@@ -333,8 +300,7 @@ class AuthService(AuthServiceABC):
|
||||
# update first name
|
||||
if (
|
||||
update_user_dto.new_auth_user.first_name is not None
|
||||
and update_user_dto.auth_user.first_name
|
||||
!= update_user_dto.new_auth_user.first_name
|
||||
and update_user_dto.auth_user.first_name != update_user_dto.new_auth_user.first_name
|
||||
):
|
||||
user.first_name = update_user_dto.new_auth_user.first_name
|
||||
|
||||
@@ -342,8 +308,7 @@ class AuthService(AuthServiceABC):
|
||||
if (
|
||||
update_user_dto.new_auth_user.last_name is not None
|
||||
and update_user_dto.new_auth_user.last_name != ""
|
||||
and update_user_dto.auth_user.last_name
|
||||
!= update_user_dto.new_auth_user.last_name
|
||||
and update_user_dto.auth_user.last_name != update_user_dto.new_auth_user.last_name
|
||||
):
|
||||
user.last_name = update_user_dto.new_auth_user.last_name
|
||||
|
||||
@@ -353,33 +318,22 @@ class AuthService(AuthServiceABC):
|
||||
and update_user_dto.new_auth_user.email != ""
|
||||
and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email
|
||||
):
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(
|
||||
update_user_dto.new_auth_user.email
|
||||
)
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email)
|
||||
if user_by_new_e_mail is not None:
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidUser, "User already exists"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
|
||||
user.email = update_user_dto.new_auth_user.email
|
||||
|
||||
update_user_dto.auth_user.password = self._hash_sha256(
|
||||
update_user_dto.auth_user.password, user.password_salt
|
||||
)
|
||||
update_user_dto.auth_user.password = self._hash_sha256(update_user_dto.auth_user.password, user.password_salt)
|
||||
if update_user_dto.auth_user.password != user.password:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password")
|
||||
|
||||
# update password
|
||||
if (
|
||||
update_user_dto.new_auth_user.password is not None
|
||||
and self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
!= user.password
|
||||
and self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt) != user.password
|
||||
):
|
||||
user.password_salt = uuid.uuid4()
|
||||
user.password = self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
|
||||
|
||||
self._auth_users.update_auth_user(user)
|
||||
self._db.save_changes()
|
||||
@@ -389,31 +343,23 @@ class AuthService(AuthServiceABC):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty")
|
||||
|
||||
if update_user_dto.auth_user is None:
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidData, f"Existing user is empty"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Existing user is empty")
|
||||
|
||||
if update_user_dto.new_auth_user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"New user is empty")
|
||||
|
||||
if not self._is_email_valid(
|
||||
update_user_dto.auth_user.email
|
||||
) or not self._is_email_valid(update_user_dto.new_auth_user.email):
|
||||
if not self._is_email_valid(update_user_dto.auth_user.email) or not self._is_email_valid(
|
||||
update_user_dto.new_auth_user.email
|
||||
):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Invalid E-Mail")
|
||||
|
||||
user = self._auth_users.find_auth_user_by_email(update_user_dto.auth_user.email)
|
||||
if user is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User not found")
|
||||
|
||||
if (
|
||||
user.confirmation_id is not None
|
||||
and update_user_dto.new_auth_user.is_confirmed
|
||||
):
|
||||
if user.confirmation_id is not None and update_user_dto.new_auth_user.is_confirmed:
|
||||
user.confirmation_id = None
|
||||
elif (
|
||||
user.confirmation_id is None
|
||||
and not update_user_dto.new_auth_user.is_confirmed
|
||||
):
|
||||
elif user.confirmation_id is None and not update_user_dto.new_auth_user.is_confirmed:
|
||||
user.confirmation_id = uuid.uuid4()
|
||||
# else
|
||||
# raise ServiceException(ServiceErrorCode.InvalidUser, 'E-Mail not confirmed')
|
||||
@@ -421,8 +367,7 @@ class AuthService(AuthServiceABC):
|
||||
# update first name
|
||||
if (
|
||||
update_user_dto.new_auth_user.first_name is not None
|
||||
and update_user_dto.auth_user.first_name
|
||||
!= update_user_dto.new_auth_user.first_name
|
||||
and update_user_dto.auth_user.first_name != update_user_dto.new_auth_user.first_name
|
||||
):
|
||||
user.first_name = update_user_dto.new_auth_user.first_name
|
||||
|
||||
@@ -430,8 +375,7 @@ class AuthService(AuthServiceABC):
|
||||
if (
|
||||
update_user_dto.new_auth_user.last_name is not None
|
||||
and update_user_dto.new_auth_user.last_name != ""
|
||||
and update_user_dto.auth_user.last_name
|
||||
!= update_user_dto.new_auth_user.last_name
|
||||
and update_user_dto.auth_user.last_name != update_user_dto.new_auth_user.last_name
|
||||
):
|
||||
user.last_name = update_user_dto.new_auth_user.last_name
|
||||
|
||||
@@ -441,28 +385,19 @@ class AuthService(AuthServiceABC):
|
||||
and update_user_dto.new_auth_user.email != ""
|
||||
and update_user_dto.auth_user.email != update_user_dto.new_auth_user.email
|
||||
):
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(
|
||||
update_user_dto.new_auth_user.email
|
||||
)
|
||||
user_by_new_e_mail = self._auth_users.find_auth_user_by_email(update_user_dto.new_auth_user.email)
|
||||
if user_by_new_e_mail is not None:
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidUser, "User already exists"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists")
|
||||
user.email = update_user_dto.new_auth_user.email
|
||||
|
||||
# update password
|
||||
if (
|
||||
update_user_dto.new_auth_user.password is not None
|
||||
and update_user_dto.change_password
|
||||
and user.password
|
||||
!= self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
and user.password != self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
|
||||
):
|
||||
user.password_salt = uuid.uuid4()
|
||||
user.password = self._hash_sha256(
|
||||
update_user_dto.new_auth_user.password, user.password_salt
|
||||
)
|
||||
user.password = self._hash_sha256(update_user_dto.new_auth_user.password, user.password_salt)
|
||||
|
||||
# update role
|
||||
if (
|
||||
@@ -481,9 +416,7 @@ class AuthService(AuthServiceABC):
|
||||
self._db.save_changes()
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Cannot delete user", e)
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.UnableToDelete, f"Cannot delete user by mail {email}"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.UnableToDelete, f"Cannot delete user by mail {email}")
|
||||
|
||||
async def delete_auth_user_async(self, user_dto: AuthUser):
|
||||
try:
|
||||
@@ -567,9 +500,7 @@ class AuthService(AuthServiceABC):
|
||||
if user.id in user_ids:
|
||||
continue
|
||||
|
||||
self._auth_users.add_auth_user_user_rel(
|
||||
AuthUserUsersRelation(db_user, user)
|
||||
)
|
||||
self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, user))
|
||||
|
||||
if db_user.confirmation_id is not None and not added_user:
|
||||
raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified")
|
||||
@@ -599,19 +530,13 @@ class AuthService(AuthServiceABC):
|
||||
):
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token expired")
|
||||
|
||||
return TokenDTO(
|
||||
self.generate_token(user), self._create_and_save_refresh_token(user)
|
||||
)
|
||||
return TokenDTO(self.generate_token(user), self._create_and_save_refresh_token(user))
|
||||
except Exception as e:
|
||||
self._logger.error(__name__, f"Refreshing token failed", e)
|
||||
return TokenDTO("", "")
|
||||
|
||||
async def revoke_async(self, token_dto: TokenDTO):
|
||||
if (
|
||||
token_dto is None
|
||||
or token_dto.token is None
|
||||
or token_dto.refresh_token is None
|
||||
):
|
||||
if token_dto is None or token_dto.token is None or token_dto.refresh_token is None:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token not set")
|
||||
|
||||
try:
|
||||
@@ -664,9 +589,7 @@ class AuthService(AuthServiceABC):
|
||||
)
|
||||
|
||||
if user.confirmation_id is not None:
|
||||
raise ServiceException(
|
||||
ServiceErrorCode.InvalidUser, f"E-Mail not confirmed"
|
||||
)
|
||||
raise ServiceException(ServiceErrorCode.InvalidUser, f"E-Mail not confirmed")
|
||||
|
||||
if user.password is None or rp_dto.password == "":
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, f"Password not set")
|
@@ -53,17 +53,13 @@ class DiscordService:
|
||||
if role != AuthRoleEnum.admin:
|
||||
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||
if auth_user is not None:
|
||||
user_ids = auth_user.users.select(
|
||||
lambda x: x.server is not None and x.server.id
|
||||
)
|
||||
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
|
||||
servers = servers.where(lambda x: x.id in user_ids)
|
||||
|
||||
servers = List(ServerDTO, servers)
|
||||
return servers.select(self._to_dto).where(lambda x: x.name != "")
|
||||
|
||||
async def get_filtered_servers_async(
|
||||
self, criteria: ServerSelectCriteria
|
||||
) -> ServerFilteredResultDTO:
|
||||
async def get_filtered_servers_async(self, criteria: ServerSelectCriteria) -> ServerFilteredResultDTO:
|
||||
token = self._auth.get_decoded_token_from_request()
|
||||
if token is None or "email" not in token or "role" not in token:
|
||||
raise ServiceException(ServiceErrorCode.InvalidData, "Token invalid")
|
||||
@@ -74,22 +70,15 @@ class DiscordService:
|
||||
if role != AuthRoleEnum.admin:
|
||||
auth_user = self._auth_users.find_auth_user_by_email(token["email"])
|
||||
if auth_user is not None:
|
||||
user_ids = auth_user.users.select(
|
||||
lambda x: x.server is not None and x.server.id
|
||||
)
|
||||
filtered_result.result = filtered_result.result.where(
|
||||
lambda x: x.id in user_ids
|
||||
)
|
||||
user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id)
|
||||
filtered_result.result = filtered_result.result.where(lambda x: x.id in user_ids)
|
||||
|
||||
servers: List = filtered_result.result.select(self._to_dto).where(
|
||||
lambda x: x.name != ""
|
||||
)
|
||||
servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "")
|
||||
result = List(ServerDTO, servers)
|
||||
|
||||
if criteria.name is not None and criteria.name != "":
|
||||
result = result.where(
|
||||
lambda x: criteria.name.lower() in x.name.lower()
|
||||
or x.name.lower() == criteria.name.lower()
|
||||
lambda x: criteria.name.lower() in x.name.lower() or x.name.lower() == criteria.name.lower()
|
||||
)
|
||||
|
||||
return ServerFilteredResultDTO(List(ServerDTO, result), servers.count())
|
||||
@@ -98,7 +87,5 @@ class DiscordService:
|
||||
server = self._servers.get_server_by_id(id)
|
||||
guild = self._bot.get_guild(server.discord_id)
|
||||
|
||||
server_dto = ServerTransformer.to_dto(
|
||||
server, guild.name, guild.member_count, guild.icon
|
||||
)
|
||||
server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon)
|
||||
return server_dto
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user