Compare commits

..

No commits in common. "1c02608410198411d79c9d4049ab8623b23f8f01" and "eeda0405f3a0b57ee20b701556f22e07eaaaed0f" have entirely different histories.

826 changed files with 1301 additions and 3806 deletions

View File

@ -22,48 +22,36 @@ jobs:
- name: Clone Repository - name: Clone Repository
uses: https://github.com/actions/checkout@v3 uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }} - name: Shutdown stack
submodules: true run: docker stack rm kdb_staging
- name: Prepare bot build - name: Prepare bot build
run: | run: |
cd bot cd kdb-bot
pip install --extra-index-url https://pip.sh-edraft.de cpl-cli pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cpl i cpl i
- name: Build docker bot
run: |
cd kdb-bot
docker image prune -f
cpl docker-build
- name: Setup node - name: Setup node
uses: https://github.com/actions/setup-node@v3 uses: https://github.com/actions/setup-node@v3
- name: Prepare web build - name: Prepare web build
run: | run: |
cd web cd kdb-web
npm install -g ts-node npm install -g ts-node
npm ci npm i
- name: Shutdown stack
run: docker stack rm sdb_dev
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t sh-edraft.de/sdb-bot:$(cpl gv)-dev .
- name: Build docker web - name: Build docker web
run: | run: |
cd web cd kdb-web
docker image prune -f docker image prune -f
cp src/favicon.dev.ico src/favicon.ico npm run docker-build
npm run build
docker build -t sh-edraft.de/sdb-web:$(npm run -s gv)-dev .
- name: Set version
run: |
cd bot/docker
chmod +x ./set-docker-compose-image-version.sh
./set-docker-compose-image-version.sh sh-edraft.de/sdb-bot:$(cd ../; cpl gv)-dev sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)-dev
- name: Deploy Stack to sh-edraft.de - name: Deploy Stack to sh-edraft.de
uses: https://github.com/kgierke/portainer-stack-deployment@v1 uses: https://github.com/kgierke/portainer-stack-deployment@v1
@ -72,6 +60,6 @@ jobs:
portainer-username: "gitea_job" portainer-username: "gitea_job"
portainer-password: "${{ secrets.docker_job }}" portainer-password: "${{ secrets.docker_job }}"
portainer-endpoint: 2 portainer-endpoint: 2
name: sdb_dev name: kdb_staging
file: bot/docker/docker-compose.dev.yml file: ./docker-compose.staging.yml
variables: '{}' variables: '{}'

View File

@ -1,5 +1,5 @@
name: Deploy prod on push name: Deploy dev on push
run-name: Deploy prod on push run-name: Deploy dev on push
on: on:
push: push:
branches: branches:
@ -22,47 +22,36 @@ jobs:
- name: Clone Repository - name: Clone Repository
uses: https://github.com/actions/checkout@v3 uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }} - name: Shutdown stack
submodules: true run: docker stack rm kdb_prod
- name: Prepare bot build - name: Prepare bot build
run: | run: |
cd bot cd kdb-bot
pip install --extra-index-url https://pip.sh-edraft.de cpl-cli pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cpl i cpl i
- name: Build docker bot
run: |
cd kdb-bot
docker image prune -f
cpl docker-build
- name: Setup node - name: Setup node
uses: https://github.com/actions/setup-node@v3 uses: https://github.com/actions/setup-node@v3
- name: Prepare web build - name: Prepare web build
run: | run: |
cd web cd kdb-web
npm install -g ts-node npm install -g ts-node
npm ci npm i
- name: Shutdown stack
run: docker stack rm sdb_prod
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t sh-edraft.de/sdb-bot:$(cpl gv) .
- name: Build docker web - name: Build docker web
run: | run: |
cd web cd kdb-web
docker image prune -f docker image prune -f
npm run build npm run docker-build
docker build -t sh-edraft.de/sdb-web:$(npm run -s gv) .
- name: Set version
run: |
cd bot/docker
chmod +x ./set-docker-compose-image-version.sh
./set-docker-compose-image-version.sh sh-edraft.de/sdb-bot:$(cd ../; cpl gv) sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)
- name: Deploy Stack to sh-edraft.de - name: Deploy Stack to sh-edraft.de
uses: https://github.com/kgierke/portainer-stack-deployment@v1 uses: https://github.com/kgierke/portainer-stack-deployment@v1
@ -71,6 +60,6 @@ jobs:
portainer-username: "gitea_job" portainer-username: "gitea_job"
portainer-password: "${{ secrets.docker_job }}" portainer-password: "${{ secrets.docker_job }}"
portainer-endpoint: 2 portainer-endpoint: 2
name: sdb_prod name: kdb_prod
file: bot/docker/docker-compose.yml file: ./docker-compose.yml
variables: '{}' variables: '{}'

View File

@ -1,77 +0,0 @@
name: Deploy staging on push
run-name: Deploy staging on push
on:
push:
branches:
- staging
jobs:
on-push-deploy_sh-edraft:
runs-on: [ dobby.sh-edraft.de, ubuntu-latest ]
container: catthehacker/ubuntu:act-latest
steps:
- name: Setup Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10.12"
- run: python -v
- name: Setup docker
uses: https://github.com/papodaca/install-docker-action@main
- run: docker -v
- name: Clone Repository
uses: https://github.com/actions/checkout@v3
with:
token: ${{ secrets.CI_ACCESS_TOKEN }}
submodules: true
- name: Prepare bot build
run: |
cd bot
pip install --extra-index-url https://pip.sh-edraft.de cpl-cli
cpl i
- name: Setup node
uses: https://github.com/actions/setup-node@v3
- name: Prepare web build
run: |
cd web
npm install -g ts-node
npm ci
- name: Shutdown stack
run: docker stack rm sdb_staging
- name: Build docker bot
run: |
cd bot
docker image prune -f
cpl build
docker build -t sh-edraft.de/sdb-bot:$(cpl gv)-staging .
- name: Build docker web
run: |
cd web
docker image prune -f
cp src/favicon.staging.ico src/favicon.ico
npm run build
docker build -t sh-edraft.de/sdb-web:$(npm run -s gv)-staging .
- name: Set version
run: |
cd bot/docker
chmod +x ./set-docker-compose-image-version.sh
./set-docker-compose-image-version.sh sh-edraft.de/sdb-bot:$(cd ../; cpl gv)-staging sh-edraft.de/sdb-web:$(cd ../../web; npm run -s gv;)-staging
- name: Deploy Stack to sh-edraft.de
uses: https://github.com/kgierke/portainer-stack-deployment@v1
with:
portainer-url: "https://docker.sh-edraft.de"
portainer-username: "gitea_job"
portainer-password: "${{ secrets.docker_job }}"
portainer-endpoint: 2
name: sdb_staging
file: bot/docker/docker-compose.staging.yml
variables: '{}'

18
.gitmodules vendored
View File

@ -1,9 +1,9 @@
[submodule "bot/src/bot/config"] [submodule "kdb-bot/src/bot/config"]
path = bot/src/bot/config path = kdb-bot/src/bot/config
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.config.git url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.config.git
[submodule "bot/src/bot_api/config"] [submodule "kdb-bot/src/bot_api/config"]
path = bot/src/bot_api/config path = kdb-bot/src/bot_api/config
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.api.config.git url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.api.config.git
[submodule "bot/docker"] [submodule "kdb-bot/docker"]
path = bot/docker path = kdb-bot/docker
url = https://git.sh-edraft.de/sh-edraft.de/sh_discord_bot.docker.git url = https://git.sh-edraft.de/sh-edraft.de/kd_discord_bot.docker.git

@ -1 +0,0 @@
Subproject commit 9634f3e4d7ecdba619bd4596b18d407f88b281cc

@ -1 +0,0 @@
Subproject commit 954fd9bb341ff9ad66ffc9e293cbcde6ecb71326

@ -1 +0,0 @@
Subproject commit f51429090df0bac7c93622e8fb3eac9dd1b9a5e7

View File

@ -1,28 +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()

View File

@ -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)

View File

@ -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

View File

@ -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;
"""
)
)

View File

@ -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;

View File

@ -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;
"""
)
)

View File

@ -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;
"""
)
)

View File

@ -1,115 +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};
"""
)

View File

@ -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

View File

@ -1,73 +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)

View File

@ -1,56 +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

View File

@ -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
}

View File

@ -1,90 +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)

View File

@ -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)

View File

@ -1,17 +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)

View File

@ -1,67 +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()

View File

@ -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")

View File

@ -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": []
}
}

View File

@ -1,22 +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

View File

@ -1,217 +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&filter=topsellers"
)
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 = 250 # only look at first 500
# todo: let admins change the value
self._logger.debug(__name__, f"Get special offers from 0 to {sale_count}")
for i in range(0, sale_count, 100):
if i > sale_count:
break
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(hours=1)
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()

View File

@ -17,7 +17,6 @@
"permission": "src/modules/permission/permission.json", "permission": "src/modules/permission/permission.json",
"technician": "src/modules/technician/technician.json", "technician": "src/modules/technician/technician.json",
"short-role-name": "src/modules/short_role_name/short-role-name.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", "checks": "tools/checks/checks.json",
"get-version": "tools/get_version/get-version.json", "get-version": "tools/get_version/get-version.json",
"post-build": "tools/post_build/post-build.json", "post-build": "tools/post_build/post-build.json",
@ -32,12 +31,12 @@
"pre-build": "cpl set-version $ARGS; black ./;", "pre-build": "cpl set-version $ARGS; black ./;",
"post-build": "cpl run post-build --dev; black ./;", "post-build": "cpl run post-build --dev; black ./;",
"pre-prod": "cpl build", "pre-prod": "cpl build",
"prod": "export SDB_ENVIRONMENT=production; export SDB_NAME=SDB-Prod; cpl start;", "prod": "export KDB_ENVIRONMENT=production; export KDB_NAME=KDB-Prod; cpl start;",
"pre-stage": "cpl build", "pre-stage": "cpl build",
"stage": "export SDB_ENVIRONMENT=staging; export SDB_NAME=SDB-Stage; cpl start;", "stage": "export KDB_ENVIRONMENT=staging; export KDB_NAME=KDB-Stage; cpl start;",
"pre-dev": "cpl build", "pre-dev": "cpl build",
"dev": "export SDB_ENVIRONMENT=development; export SDB_NAME=SDB-Dev; cpl start;", "dev": "export KDB_ENVIRONMENT=development; export KDB_NAME=KDB-Dev; cpl start;",
"docker-build": "cpl build $ARGS; docker build -t sh-edraft.de/sdb-bot:$(cpl gv) .;", "docker-build": "cpl build $ARGS; docker build -t sh-edraft.de/kdb-bot:$(cpl gv) .;",
"dc-up": "docker-compose up -d", "dc-up": "docker-compose up -d",
"dc-down": "docker-compose down", "dc-down": "docker-compose down",
"docker": "cpl dc-down; cpl docker-build; cpl dc-up;" "docker": "cpl dc-down; cpl docker-build; cpl dc-up;"

1
kdb-bot/docker Submodule

@ -0,0 +1 @@
Subproject commit 7ae4783874d5aa8015d8f0da2c19c293fcd72762

View File

@ -2,7 +2,7 @@
FROM python:3.10.4-alpine FROM python:3.10.4-alpine
WORKDIR /app WORKDIR /app
COPY ./dist/bot/build/bot/ . COPY ./dist/bot/build/kdb-bot/ .
COPY ./dist/bot/build/requirements.txt . COPY ./dist/bot/build/requirements.txt .
RUN python -m pip install --upgrade pip RUN python -m pip install --upgrade pip

View File

@ -15,7 +15,7 @@ __title__ = "bot"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -8,7 +8,6 @@ from cpl_discord.service import DiscordBotServiceABC, DiscordBotService
from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings from cpl_translation import TranslatePipe, TranslationServiceABC, TranslationSettings
from bot_api.api_thread import ApiThread 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_enum import FeatureFlagsEnum
from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings
from bot_core.service.data_integrity_service import DataIntegrityService from bot_core.service.data_integrity_service import DataIntegrityService
@ -30,8 +29,6 @@ class Application(DiscordBotApplicationABC):
# cpl-translation # cpl-translation
self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC) self._translation: TranslationServiceABC = services.get_service(TranslationServiceABC)
self._t: TranslatePipe = services.get_service(TranslatePipe) 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)
@ -58,9 +55,6 @@ class Application(DiscordBotApplicationABC):
return return
self._logger.info(__name__, f"Try to start {DiscordBotService.__name__}") 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.start_async()
await self._bot.stop_async() await self._bot.stop_async()
except Exception as e: except Exception as e:

View File

@ -3,8 +3,8 @@
"Name": "bot", "Name": "bot",
"Version": { "Version": {
"Major": "1", "Major": "1",
"Minor": "2", "Minor": "1",
"Micro": "0" "Micro": "10"
}, },
"Author": "Sven Heidemann", "Author": "Sven Heidemann",
"AuthorEmail": "sven.heidemann@sh-edraft.de", "AuthorEmail": "sven.heidemann@sh-edraft.de",
@ -16,24 +16,22 @@
"LicenseName": "MIT", "LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.", "LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [ "Dependencies": [
"cpl-core==2023.10.0", "cpl-core==2023.4.0.post5",
"cpl-translation==2023.4.0.post1", "cpl-translation==2023.4.0.post1",
"cpl-query==2023.10.0", "cpl-query==2023.4.0.post1",
"cpl-discord==2023.10.0.post1", "cpl-discord==2023.4.0.post3",
"Flask==3.0.0", "Flask==2.3.2",
"Flask-Classful==0.16.0", "Flask-Classful==0.14.2",
"Flask-Cors==4.0.0", "Flask-Cors==4.0.0",
"PyJWT==2.8.0", "PyJWT==2.8.0",
"waitress==2.1.2", "waitress==2.1.2",
"Flask-SocketIO==5.3.6", "Flask-SocketIO==5.3.4",
"eventlet==0.33.3", "eventlet==0.33.3",
"requests-oauthlib==1.3.1", "requests-oauthlib==1.3.1",
"icmplib==3.0.4", "icmplib==3.0.3",
"ariadne==0.20.1", "ariadne==0.20.1",
"cryptography==41.0.4", "cryptography==41.0.2",
"discord==2.3.2", "discord>=2.3.2"
"bs4==0.0.1",
"lxml==4.9.3"
], ],
"DevDependencies": [ "DevDependencies": [
"cpl-cli==2023.4.0.post3", "cpl-cli==2023.4.0.post3",
@ -71,7 +69,6 @@
"../modules/level/level.json", "../modules/level/level.json",
"../modules/permission/permission.json", "../modules/permission/permission.json",
"../modules/short_role_name/short-role-name.json", "../modules/short_role_name/short-role-name.json",
"../modules/special_offers/special-offers.json",
"../modules/technician/technician.json" "../modules/technician/technician.json"
] ]
} }

@ -0,0 +1 @@
Subproject commit 23eafb2e211241acbbc52833d139c67f1ecc69f5

View File

@ -15,7 +15,7 @@ __title__ = "bot.extension"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -14,7 +14,6 @@ from modules.database.database_module import DatabaseModule
from modules.level.level_module import LevelModule from modules.level.level_module import LevelModule
from modules.permission.permission_module import PermissionModule from modules.permission.permission_module import PermissionModule
from modules.short_role_name.short_role_name_module import ShortRoleNameModule 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 from modules.technician.technician_module import TechnicianModule
@ -38,7 +37,6 @@ class ModuleList:
TechnicianModule, TechnicianModule,
AchievementsModule, AchievementsModule,
ShortRoleNameModule, ShortRoleNameModule,
SteamSpecialOffersModule,
# has to be last! # has to be last!
BootLogModule, BootLogModule,
CoreExtensionModule, CoreExtensionModule,

View File

@ -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.command_logger import CommandLogger
from bot_core.logging.database_logger import DatabaseLogger from bot_core.logging.database_logger import DatabaseLogger
from bot_core.logging.message_logger import MessageLogger from bot_core.logging.message_logger import MessageLogger
from bot_core.logging.task_logger import TaskLogger
from bot_data.db_context import DBContext from bot_data.db_context import DBContext
@ -44,7 +43,6 @@ class Startup(StartupABC):
services.add_singleton(CustomFileLoggerABC, CommandLogger) services.add_singleton(CustomFileLoggerABC, CommandLogger)
services.add_singleton(CustomFileLoggerABC, DatabaseLogger) services.add_singleton(CustomFileLoggerABC, DatabaseLogger)
services.add_singleton(CustomFileLoggerABC, MessageLogger) services.add_singleton(CustomFileLoggerABC, MessageLogger)
services.add_singleton(CustomFileLoggerABC, TaskLogger)
if self._feature_flags.get_flag(FeatureFlagsEnum.api_module): if self._feature_flags.get_flag(FeatureFlagsEnum.api_module):
services.add_singleton(CustomFileLoggerABC, ApiLogger) services.add_singleton(CustomFileLoggerABC, ApiLogger)

View File

@ -9,27 +9,18 @@ from bot_data.migration.api_key_migration import ApiKeyMigration
from bot_data.migration.api_migration import ApiMigration from bot_data.migration.api_migration import ApiMigration
from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration
from bot_data.migration.auto_role_migration import AutoRoleMigration 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_feature_flags_migration import (
ConfigFeatureFlagsMigration,
)
from bot_data.migration.config_migration import ConfigMigration from bot_data.migration.config_migration import ConfigMigration
from bot_data.migration.db_history_migration import DBHistoryMigration from bot_data.migration.db_history_migration import DBHistoryMigration
from bot_data.migration.default_role_migration import DefaultRoleMigration from bot_data.migration.default_role_migration import DefaultRoleMigration
from bot_data.migration.fix_updates_migration import FixUpdatesMigration 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.initial_migration import InitialMigration
from bot_data.migration.level_migration import LevelMigration from bot_data.migration.level_migration import LevelMigration
from bot_data.migration.remove_stats_migration import RemoveStatsMigration 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_migration import ShortRoleNameMigration
from bot_data.migration.short_role_name_only_highest_migration import ( from bot_data.migration.short_role_name_only_highest_migration import ShortRoleNameOnlyHighestMigration
ShortRoleNameOnlyHighestMigration,
)
from bot_data.migration.stats_migration import StatsMigration 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_joined_game_server_migration import (
UserJoinedGameServerMigration,
)
from bot_data.migration.user_message_count_per_hour_migration import ( from bot_data.migration.user_message_count_per_hour_migration import (
UserMessageCountPerHourMigration, UserMessageCountPerHourMigration,
) )
@ -65,6 +56,3 @@ class StartupMigrationExtension(StartupExtensionABC):
services.add_transient(MigrationABC, ShortRoleNameMigration) # 28.09.2023 #378 - 1.1.7 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, FixUpdatesMigration) # 28.09.2023 #378 - 1.1.7
services.add_transient(MigrationABC, ShortRoleNameOnlyHighestMigration) # 02.10.2023 #391 - 1.1.9 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

View File

@ -17,7 +17,7 @@ class StartupSettingsExtension(StartupExtensionABC):
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 # 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__))) environment.set_working_directory(os.path.dirname(os.path.realpath(__file__)))
configuration.add_environment_variables("SDB_") configuration.add_environment_variables("KDB_")
configuration.add_environment_variables("DISCORD_") configuration.add_environment_variables("DISCORD_")
configuration.add_json_file(f"config/appsettings.json", optional=False) configuration.add_json_file(f"config/appsettings.json", optional=False)

View File

@ -94,11 +94,6 @@
} }
}, },
"modules": { "modules": {
"special_offers": {
"price": "Preis",
"discount": "Rabatt",
"discount_price": "Neuer Preis"
},
"achievements": { "achievements": {
"commands": { "commands": {
"check": "Alles klar, ich schaue eben nach... nom nom" "check": "Alles klar, ich schaue eben nach... nom nom"
@ -234,11 +229,6 @@
"success": "Verlinkung wurde entfernt :D" "success": "Verlinkung wurde entfernt :D"
}, },
"user": { "user": {
"birthday": {
"has_birthday": "Alles Gute zum Geburtag {} :D",
"success": "Dein Geburtstag wurde eingetragen.",
"success_team": "{} hat seinen Geburtstag eingetragen: {}"
},
"add": { "add": {
"xp": "Die {} von {} wurden um {} erhöht" "xp": "Die {} von {} wurden um {} erhöht"
}, },

View File

@ -15,7 +15,7 @@ __title__ = "bot_api"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.abc"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -149,10 +149,7 @@ class Api(Flask):
return response return response
def start(self): def start(self):
self._logger.info( self._logger.info(__name__, f"Starting API {self._api_settings.host}:{self._api_settings.port}")
__name__,
f"Starting API {self._api_settings.host}:{self._api_settings.port}",
)
self._register_routes() self._register_routes()
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key) self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
# from waitress import serve # from waitress import serve

View File

@ -48,4 +48,4 @@ class ApiModule(ModuleABC):
services.add_transient(GraphQLController) services.add_transient(GraphQLController)
# cpl-discord # cpl-discord
services.add_transient(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent) self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent)

View File

@ -3,8 +3,8 @@
"Name": "bot-api", "Name": "bot-api",
"Version": { "Version": {
"Major": "1", "Major": "1",
"Minor": "2", "Minor": "1",
"Micro": "0" "Micro": "10"
}, },
"Author": "", "Author": "",
"AuthorEmail": "", "AuthorEmail": "",

@ -0,0 +1 @@
Subproject commit b6ffed4da1f75f5fbad1ce7f312b67f32de010b5

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.configuration"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports # imports
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.controller"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.event"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.exception"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.filter"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.filter.discord"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.logging"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.model"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -15,7 +15,7 @@ __title__ = "bot_api.model.discord"
__author__ = "Sven Heidemann" __author__ = "Sven Heidemann"
__license__ = "MIT" __license__ = "MIT"
__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de"
__version__ = "1.2.0" __version__ = "1.1.10"
from collections import namedtuple from collections import namedtuple
@ -23,4 +23,4 @@ from collections import namedtuple
# imports: # imports:
VersionInfo = namedtuple("VersionInfo", "major minor micro") VersionInfo = namedtuple("VersionInfo", "major minor micro")
version_info = VersionInfo(major="1", minor="2", micro="0") version_info = VersionInfo(major="1", minor="1", micro="10")

View File

@ -27,8 +27,4 @@ class TokenDTO(DtoABC):
self._first_login = values["firstLogin"] self._first_login = values["firstLogin"]
def to_dict(self) -> dict: def to_dict(self) -> dict:
return { return {"token": self._token, "refreshToken": self._refresh_token, "firstLogin": self._first_login}
"token": self._token,
"refreshToken": self._refresh_token,
"firstLogin": self._first_login,
}

Some files were not shown because too many files have changed in this diff Show More