diff --git a/agb.html b/agb.html new file mode 100644 index 0000000..be3ec36 --- /dev/null +++ b/agb.html @@ -0,0 +1,18 @@ + + + + + + Nutzungsbedingungen (AGB) - ManagerX + + + + + + + + +
+ + + diff --git a/datenschutz.html b/datenschutz.html new file mode 100644 index 0000000..e8a4750 --- /dev/null +++ b/datenschutz.html @@ -0,0 +1,18 @@ + + + + + + Datenschutz - ManagerX + + + + + + + + +
+ + + diff --git a/examples/bot/embeds.py b/examples/bot/embeds.py new file mode 100644 index 0000000..ac19583 --- /dev/null +++ b/examples/bot/embeds.py @@ -0,0 +1,35 @@ +# How Works Embeds? + +import discord +from discord import slash_command +import ezcord + +class Embeds(ezcord.Cog): + def __init__(self, bot): + self.bot = bot + + @slash_command(name="embed", description="Embeds") + async def embed(self, ctx): + embed = discord.Embed( + title="Hello World!", # Embed Title + description="This is a embed", # Embed Description + color=discord.Color.blue() # Embed Color + ) + embed.set_author( + name="Embeds", # Embed Author Name + icon_url=self.bot.user.avatar.url # Embed Author Icon + ) + embed.set_footer( + text="Embeds", # Embed Footer Text + icon_url=self.bot.user.avatar.url # Embed Footer Icon + ) + embed.set_thumbnail( + url=self.bot.user.avatar.url # Embed Thumbnail + ) + embed.set_image( + url=self.bot.user.avatar.url # Embed Image + ) + await ctx.respond(embed=embed) + +def setup(bot): + bot.add_cog(Embeds(bot)) # Add the Cog to the Bot \ No newline at end of file diff --git a/impressum.html b/impressum.html new file mode 100644 index 0000000..2284dec --- /dev/null +++ b/impressum.html @@ -0,0 +1,18 @@ + + + + + + Impressum - ManagerX + + + + + + + + +
+ + + diff --git a/src/api/dashboard/routes.py b/src/api/dashboard/routes.py index 03edf98..2ed0e7a 100644 --- a/src/api/dashboard/routes.py +++ b/src/api/dashboard/routes.py @@ -6,7 +6,7 @@ # Wir erstellen einen Router, den wir später in die Haupt-App einbinden router = APIRouter( - prefix="/api/v1/managerx", + prefix="/v1/managerx", tags=["dashboard"] ) diff --git a/src/bot/cogs/fun/4gewinnt.py b/src/bot/cogs/fun/4gewinnt.py index 9af9f1c..1fd08a4 100644 --- a/src/bot/cogs/fun/4gewinnt.py +++ b/src/bot/cogs/fun/4gewinnt.py @@ -19,6 +19,8 @@ ROWS = 6 COLUMNS = 7 DEFAULT_TIMEOUT = 300 # 5 Minuten +ACTIVE_AI_GAMES = 0 +MAX_AI_GAMES = 5 # Improved difficulty levels with better depth and strategy DIFFICULTY_CONFIG = { @@ -489,7 +491,7 @@ async def callback(self, interaction: discord.Interaction): ) class Connect4View(View): - def __init__(self, player1, player2, messages, is_ai_mode=False, difficulty="medium"): + def __init__(self, player1, player2, messages, is_ai_mode=False, difficulty="medium", on_cleanup=None): super().__init__(timeout=DEFAULT_TIMEOUT) self.player1 = player1 self.player2 = player2 @@ -504,6 +506,8 @@ def __init__(self, player1, player2, messages, is_ai_mode=False, difficulty="med self.move_count = 0 self.move_history: List[tuple] = [] self.game_ended = False + self.on_cleanup = on_cleanup + self.cleaned_up = False for col in range(COLUMNS): self.add_item(Connect4Button(col, self)) @@ -673,6 +677,10 @@ async def end_game(self, interaction: discord.Interaction, winner: bool, board_s else: await interaction.response.edit_message(embed=embed, view=self) + if self.on_cleanup and not self.cleaned_up: + self.on_cleanup() + self.cleaned_up = True + self.stop() async def on_timeout(self): @@ -680,6 +688,10 @@ async def on_timeout(self): self.game_ended = True for child in self.children: child.disabled = True + + if self.on_cleanup and not self.cleaned_up: + self.on_cleanup() + self.cleaned_up = True # ─────────────────────────────────────────────── # >> Cog @@ -712,8 +724,22 @@ async def connect4( # AI mode if opponent is None: + global ACTIVE_AI_GAMES + if ACTIVE_AI_GAMES >= MAX_AI_GAMES: + await ctx.respond( + "Tut uns leid, unsere KI wird gerade stark beansprucht. Bitte warte einen Moment damit unsere CPU last nicht in das Unendliche geht", + ephemeral=True + ) + return + + ACTIVE_AI_GAMES += 1 + + def cleanup(): + global ACTIVE_AI_GAMES + ACTIVE_AI_GAMES -= 1 + ai_user = ctx.guild.me - view = Connect4View(ctx.author, ai_user, messages, is_ai_mode=True, difficulty=difficulty) + view = Connect4View(ctx.author, ai_user, messages, is_ai_mode=True, difficulty=difficulty, on_cleanup=cleanup) difficulty_info = DIFFICULTY_CONFIG.get(difficulty, DIFFICULTY_CONFIG["medium"]) difficulty_emoji = {"easy": "😊", "medium": "🤔", "hard": "😈"} diff --git a/src/bot/cogs/fun/tictactoe.py b/src/bot/cogs/fun/tictactoe.py index 8d77f7f..b9fd25b 100644 --- a/src/bot/cogs/fun/tictactoe.py +++ b/src/bot/cogs/fun/tictactoe.py @@ -16,6 +16,8 @@ # >> Constants # ─────────────────────────────────────────────── DEFAULT_TIMEOUT = 120 +ACTIVE_AI_GAMES = 0 +MAX_AI_GAMES = 5 DIFFICULTY_CONFIG = { "easy": { @@ -344,7 +346,7 @@ async def callback(self, interaction: discord.Interaction): await interaction.response.edit_message(content=next_turn_msg, view=view) class TicTacToeView(View): - def __init__(self, player1, player2, messages, is_ai_mode=False, difficulty="medium"): + def __init__(self, player1, player2, messages, is_ai_mode=False, difficulty="medium", on_cleanup=None): super().__init__(timeout=DEFAULT_TIMEOUT) self.player1 = player1 self.player2 = player2 @@ -356,6 +358,8 @@ def __init__(self, player1, player2, messages, is_ai_mode=False, difficulty="med self.difficulty = difficulty self.ai = TicTacToeAI(difficulty) if is_ai_mode else None self.game_ended = False + self.on_cleanup = on_cleanup + self.cleaned_up = False for x in range(3): for y in range(3): @@ -477,6 +481,10 @@ async def end_game(self, interaction: discord.Interaction, winner: Optional[str] else: await interaction.response.edit_message(embed=embed, view=self) + if self.on_cleanup and not self.cleaned_up: + self.on_cleanup() + self.cleaned_up = True + self.stop() async def on_timeout(self): @@ -484,6 +492,10 @@ async def on_timeout(self): self.game_ended = True for child in self.children: child.disabled = True + + if self.on_cleanup and not self.cleaned_up: + self.on_cleanup() + self.cleaned_up = True # ─────────────────────────────────────────────── # >> Cog @@ -514,8 +526,22 @@ async def tictactoe( # AI mode if opponent is None: + global ACTIVE_AI_GAMES + if ACTIVE_AI_GAMES >= MAX_AI_GAMES: + await ctx.respond( + "Tut uns leid, unsere KI wird gerade stark beansprucht. Bitte warte einen Moment damit unsere CPU last nicht in das Unendliche geht", + ephemeral=True + ) + return + + ACTIVE_AI_GAMES += 1 + + def cleanup(): + global ACTIVE_AI_GAMES + ACTIVE_AI_GAMES -= 1 + ai_user = ctx.guild.me - view = TicTacToeView(ctx.author, ai_user, messages, is_ai_mode=True, difficulty=difficulty) + view = TicTacToeView(ctx.author, ai_user, messages, is_ai_mode=True, difficulty=difficulty, on_cleanup=cleanup) difficulty_info = DIFFICULTY_CONFIG.get(difficulty, DIFFICULTY_CONFIG["medium"]) difficulty_emoji = {"easy": "😊", "medium": "🤔", "hard": "😈"} diff --git a/src/web/entries/agb.tsx b/src/web/entries/agb.tsx new file mode 100644 index 0000000..b9482f3 --- /dev/null +++ b/src/web/entries/agb.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import Nutzungsbedingungen from "../pages/Nutzungsbedingungen"; +import "../index.css"; + +const queryClient = new QueryClient(); + +createRoot(document.getElementById("root")!).render( + + + + + + + +); diff --git a/src/web/entries/datenschutz.tsx b/src/web/entries/datenschutz.tsx new file mode 100644 index 0000000..5555d34 --- /dev/null +++ b/src/web/entries/datenschutz.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import Datenschutz from "../pages/Datenschutz"; +import "../index.css"; + +const queryClient = new QueryClient(); + +createRoot(document.getElementById("root")!).render( + + + + + + + +); diff --git a/src/web/entries/impressum.tsx b/src/web/entries/impressum.tsx new file mode 100644 index 0000000..1e5137e --- /dev/null +++ b/src/web/entries/impressum.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import Impressum from "../pages/Impressum"; +import "../index.css"; + +const queryClient = new QueryClient(); + +createRoot(document.getElementById("root")!).render( + + + + + + + +); diff --git a/vite.config.ts b/vite.config.ts index 81cfebb..4027700 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -28,5 +28,13 @@ export default defineConfig(({ mode }) => ({ // Optimierung für sauberen Code minify: "esbuild", reportCompressedSize: false, + rollupOptions: { + input: { + main: path.resolve(__dirname, "index.html"), + datenschutz: path.resolve(__dirname, "datenschutz.html"), + impressum: path.resolve(__dirname, "impressum.html"), + agb: path.resolve(__dirname, "agb.html"), + }, + }, }, })); \ No newline at end of file