commit b9383efe891ee6173a43ecfd62985cd8e1574b93 Author: SimolZimol <70102430+SimolZimol@users.noreply.github.com> Date: Sun Oct 26 00:05:38 2025 +0200 new file: .env.example new file: .gitignore new file: Dockerfile new file: README.md new file: app.py new file: requirements.txt diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..4e0f2f1 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +# Discord Bot Token (wird in Coolify als Umgebungsvariable gesetzt) +DISCORD_TOKEN=your_discord_bot_token_here \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fe17bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,129 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9b425e5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.10-slim + +WORKDIR /app + +RUN apt-get update && apt-get install -y \ + libffi-dev \ + libnacl-dev \ + python3-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +ENV DISCORD_TOKEN=$DISCORD_TOKEN + +CMD ["python", "app.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..ce0aacf --- /dev/null +++ b/README.md @@ -0,0 +1,128 @@ +# HOI4 ELO Discord Bot + +Ein Discord Bot für Hearts of Iron IV, der über Coolify deployed werden kann. + +## Features + +- **Basic Commands**: Ping, Info, Server-Informationen +- **HOI4 Theme**: Speziell für Hearts of Iron IV Communities +- **Docker Support**: Bereit für Deployment über Coolify +- **Error Handling**: Robuste Fehlerbehandlung +- **Logging**: Ausführliche Logs für Debugging + +## Verfügbare Befehle + +- `!ping` - Zeigt die Bot-Latenz an +- `!info` - Zeigt Bot-Informationen an +- `!help_hoi4` - Zeigt alle verfügbaren Befehle an +- `!server_info` - Zeigt Informationen über den aktuellen Server + +## Setup für Coolify + +### 1. Discord Bot erstellen + +1. Gehe zu https://discord.com/developers/applications +2. Erstelle eine neue Application +3. Gehe zu "Bot" und erstelle einen Bot +4. Kopiere den Bot Token + +### 2. Bot Permissions + +Der Bot benötigt folgende Permissions: +- `Send Messages` +- `Read Message History` +- `Use Slash Commands` +- `Embed Links` +- `Read Messages/View Channels` + +### 3. Coolify Deployment + +1. **Repository**: Verbinde dein Git Repository mit Coolify +2. **Umgebungsvariablen**: Setze folgende Variable in Coolify: + - `DISCORD_TOKEN` = Dein Bot Token + +3. **Build Settings**: + - Coolify wird automatisch das Dockerfile verwenden + - Port: Der Bot läuft als Service, kein HTTP-Port erforderlich + +4. **Deploy**: Starte das Deployment + +## Lokale Entwicklung + +### Voraussetzungen +- Python 3.10+ +- pip + +### Installation + +1. Repository klonen +2. Dependencies installieren: + ```bash + pip install -r requirements.txt + ``` + +3. `.env` Datei erstellen: + ```bash + cp .env.example .env + ``` + +4. Discord Token in `.env` eintragen: + ``` + DISCORD_TOKEN=your_actual_bot_token_here + ``` + +5. Bot starten: + ```bash + python app.py + ``` + +## Docker + +### Lokal mit Docker testen + +```bash +# Image bauen +docker build -t hoi4-elo-bot . + +# Container starten +docker run -e DISCORD_TOKEN=your_token_here hoi4-elo-bot +``` + +## Projekt Struktur + +``` +. +├── app.py # Haupt-Bot-Datei +├── requirements.txt # Python Dependencies +├── Dockerfile # Docker Konfiguration +├── .env.example # Beispiel Umgebungsvariablen +└── README.md # Diese Datei +``` + +## Erweiterungen + +Der Bot ist so strukturiert, dass du einfach weitere Commands hinzufügen kannst: + +```python +@bot.command(name='my_command') +async def my_command(ctx): + await ctx.send("Hello World!") +``` + +## Troubleshooting + +### Bot startet nicht +- Überprüfe ob der Discord Token korrekt gesetzt ist +- Schaue in die Logs: `docker logs ` + +### Bot reagiert nicht auf Befehle +- Stelle sicher, dass der Bot die richtigen Permissions hat +- Überprüfe ob Message Content Intent aktiviert ist + +### Coolify Logs anschauen +- Gehe zu deinem Coolify Service +- Klicke auf "Logs" um die Bot-Ausgabe zu sehen + +## Support + +Bei Problemen schaue in die Coolify Logs oder überprüfe die Discord Developer Console für weitere Informationen. \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..7e87f67 --- /dev/null +++ b/app.py @@ -0,0 +1,149 @@ +import discord +from discord.ext import commands +import os +import asyncio +import logging +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() + +# Configure logging +logging.basicConfig(level=logging.INFO) + +# Bot configuration +intents = discord.Intents.default() +intents.message_content = True +intents.guilds = True +intents.members = True + +bot = commands.Bot(command_prefix='!', intents=intents) + +@bot.event +async def on_ready(): + """Event triggered when the bot is ready""" + print(f'{bot.user} is online and ready!') + print(f'Bot ID: {bot.user.id}') + print(f'Discord.py Version: {discord.__version__}') + print('------') + + # Set bot status + await bot.change_presence( + activity=discord.Game(name="Hearts of Iron IV"), + status=discord.Status.online + ) + +@bot.event +async def on_guild_join(guild): + """Event triggered when the bot joins a server""" + print(f'Bot joined server "{guild.name}" (ID: {guild.id})') + +@bot.event +async def on_guild_remove(guild): + """Event triggered when the bot leaves a server""" + print(f'Bot left server "{guild.name}" (ID: {guild.id})') + +# Basic Commands +@bot.command(name='ping') +async def ping(ctx): + """Shows the bot latency""" + latency = round(bot.latency * 1000) + await ctx.send(f'🏓 Pong! Latency: {latency}ms') + +@bot.command(name='info') +async def info(ctx): + """Shows bot information""" + embed = discord.Embed( + title="🤖 Bot Information", + description="HOI4 ELO Bot - A Discord Bot for Hearts of Iron IV", + color=discord.Color.blue() + ) + embed.add_field(name="Bot Name", value=bot.user.name, inline=True) + embed.add_field(name="Bot ID", value=bot.user.id, inline=True) + embed.add_field(name="Servers", value=len(bot.guilds), inline=True) + embed.add_field(name="Discord.py Version", value=discord.__version__, inline=True) + embed.set_thumbnail(url=bot.user.avatar.url if bot.user.avatar else None) + embed.set_footer(text=f"Requested by {ctx.author}", icon_url=ctx.author.avatar.url if ctx.author.avatar else None) + + await ctx.send(embed=embed) + +@bot.command(name='help_hoi4') +async def help_hoi4(ctx): + """Shows available HOI4-related commands""" + embed = discord.Embed( + title="📋 HOI4 ELO Bot Commands", + description="Here are the available commands:", + color=discord.Color.green() + ) + + commands_list = [ + ("!ping", "Shows the bot latency"), + ("!info", "Shows bot information"), + ("!help_hoi4", "Shows this help message"), + ("!server_info", "Shows server information"), + ] + + for cmd, desc in commands_list: + embed.add_field(name=cmd, value=desc, inline=False) + + embed.set_footer(text="More commands will be added in future updates!") + await ctx.send(embed=embed) + +@bot.command(name='server_info') +async def server_info(ctx): + """Shows information about the current server""" + guild = ctx.guild + if not guild: + await ctx.send("❌ This command can only be used on a server!") + return + + embed = discord.Embed( + title=f"🏰 Server Information - {guild.name}", + color=discord.Color.orange() + ) + + embed.add_field(name="Server Name", value=guild.name, inline=True) + embed.add_field(name="Server ID", value=guild.id, inline=True) + embed.add_field(name="Members", value=guild.member_count, inline=True) + embed.add_field(name="Created", value=guild.created_at.strftime("%m/%d/%Y"), inline=True) + embed.add_field(name="Boost Level", value=guild.premium_tier, inline=True) + embed.add_field(name="Boost Count", value=guild.premium_subscription_count, inline=True) + + if guild.icon: + embed.set_thumbnail(url=guild.icon.url) + + await ctx.send(embed=embed) + +@bot.event +async def on_command_error(ctx, error): + """Handles command errors""" + if isinstance(error, commands.CommandNotFound): + await ctx.send("❌ Command not found! Use `!help_hoi4` for a list of available commands.") + elif isinstance(error, commands.MissingRequiredArgument): + await ctx.send(f"❌ Missing arguments! Command: `{ctx.command}`") + elif isinstance(error, commands.BadArgument): + await ctx.send("❌ Invalid argument!") + else: + print(f"Unknown error: {error}") + await ctx.send("❌ An unknown error occurred!") + +async def main(): + """Main function to start the bot""" + # Load Discord token from environment variables + token = os.getenv('DISCORD_TOKEN') + + if not token: + print("❌ DISCORD_TOKEN environment variable not found!") + print("Please set the DISCORD_TOKEN variable in Coolify or create a .env file") + return + + try: + print("🚀 Starting bot...") + await bot.start(token) + except discord.LoginFailure: + print("❌ Invalid Discord token!") + except Exception as e: + print(f"❌ Error starting bot: {e}") + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e4a9937 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +discord.py==2.3.2 +python-dotenv==1.0.0 +aiohttp==3.9.1 \ No newline at end of file