diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2f8ab1e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,83 @@ +# Git files +.git +.gitignore +.gitattributes + +# Python cache +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python + +# Virtual environments +venv/ +env/ +ENV/ + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Log files +*.log +bot.log +discord.log + +# Database files (these should be mounted as volumes) +*.db +*.sqlite + +# Temporary files +temp/ +tmp/ +*.tmp + +# OS files +.DS_Store +Thumbs.db + +# Documentation +README.md +*.md +docs/ + +# CI/CD +.github/ +.gitlab-ci.yml + +# Testing +tests/ +test_*.py +*_test.py + +# Old/backup files +old/ +*.bak +*.backup + +# Docker files (no need to copy these into the image) +Dockerfile* +docker-compose*.yml +.dockerignore + +# Build artifacts +build/ +dist/ +*.egg-info/ + +# Migration scripts (already applied) +apply_db_migration.py +fix_filename_column.sql + +# Schema (documentation only) +schema.sql + +# User-generated content that should be volumes +soundboard/ +voices/ +youtube/ +markov/ diff --git a/Dockerfile b/Dockerfile index 6abf102..bf14c8a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,46 @@ -# Build from basic python image -FROM python:3.8 -# Set working dir to the app folder. -WORKDIR /usr/src/app -# Clone git repo -RUN git clone https://github.com/plop91/PlopBot.git -# Set working dir to the git repo -WORKDIR /usr/src/app/PlopBot/ -# Set branch to pull from -ARG branch=ian-nightly -# fetch branchs -RUN git fetch -# Checkout branch -RUN git checkout $branch -# Create a volume so soundboard and info files can be saved on server, must mount with -v -VOLUME /usr/src/app/PlopBot/soundboard/ /usr/src/app/PlopBot/info/ /usr/src/app/PlopBot/markov/ -# Install dependencies. -RUN apt-get update && apt-get install -y ffmpeg -RUN python3 -m pip install -r requirements.txt -# Run Bot +# Use Python 3.11 slim image for smaller size +FROM python:3.11-slim + +# Set metadata +LABEL description="Discord Bot" +LABEL version="1.1" + +# Set environment variables +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PIP_NO_CACHE_DIR=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 + +# Set working directory +WORKDIR /app + +# Install system dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ffmpeg \ + && rm -rf /var/lib/apt/lists/* + +# Copy requirements first for better layer caching +COPY requirements.txt . + +# Install Python dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application code +COPY . . + +# Create necessary directories +RUN mkdir -p soundboard info markov youtube temp voices + +# Create volumes for persistent data +VOLUME ["/app/soundboard", "/app/info", "/app/markov"] + +# Create non-root user for security +RUN useradd -m -u 1000 botuser && \ + chown -R botuser:botuser /app + +# Switch to non-root user +USER botuser + +# Run the bot with configurable JSON file CMD ["python3", "BotHead.py"] diff --git a/README.md b/README.md index 70ccf06..3a17c69 100644 --- a/README.md +++ b/README.md @@ -47,12 +47,36 @@ Clone the repository and make a file named "info.json" containing the following ## Run: -### Docker: +### Docker (Recommended): -Build and run the bot making sure you mount the correct location for your source. +**Using Docker Compose:** +```bash +# Build and start the bot +docker-compose up -d + +# View logs +docker-compose logs -f + +# Stop the bot +docker-compose down ``` -docker build -t "discord" . && docker run -v PATH_TO_SOURCE_DIR:/usr/src/app/ --detach --name DiscordBot "discord" + +**Using Docker directly:** + +```bash +# Build the image +docker build -t plopbot:latest . + +# Run the container with volume mounts for persistent data +docker run -d \ + --name plopbot \ + --restart unless-stopped \ + -v $(pwd)/soundboard:/app/soundboard \ + -v $(pwd)/info:/app/info \ + -v $(pwd)/markov:/app/markov \ + -v $(pwd)/voices:/app/voices \ + plopbot:latest ``` ### Python: diff --git a/cogs/openAiCog.py b/cogs/openAiCog.py index 3c0cb96..b0beecc 100644 --- a/cogs/openAiCog.py +++ b/cogs/openAiCog.py @@ -133,26 +133,18 @@ async def gen_img(self, ctx, *args): @commands.command(pass_context=True, aliases=["editimg", "editimage", "edit_image"], brief="edit an image from a prompt using openai") -<<<<<<< HEAD - async def edit_img(self, ctx): -======= @commands.cooldown(1, 60, commands.BucketType.user) async def edit_img(self, ctx, *args): ->>>>>>> f372db8 (Fix critical bugs and security issues from code review) """ Edit an image from a prompt using openai :arg ctx: Context :return: None """ -<<<<<<< HEAD if not blacklisted(ctx.author): -======= - if not blackisted(ctx.author): if not ctx.message.attachments: await ctx.send("No image attached") return ->>>>>>> f372db8 (Fix critical bugs and security issues from code review) if ctx.message.attachments[0] is None: await ctx.send("No image attached") return @@ -164,27 +156,12 @@ async def edit_img(self, ctx, *args): png = png.resize((1024, 1024)) png.save("temp.png", 'png', quality=100) settings.logger.info(f"editing image") -<<<<<<< HEAD - response = self.openai_client.images.create_variation( - image=open("temp.png", "rb"), - n=1, - size="1024x1024" - ) -======= - # response = openai.Image.create_edit( - # image=open("temp.png", "rb"), - # mask=open("mask.png", "rb"), - # prompt=prompt, - # n=1, - # size="1024x1024" - # ) with open("temp.png", "rb") as image_file: response = self.openai_client.images.create_variation( image=image_file, n=1, size="1024x1024" ) ->>>>>>> f372db8 (Fix critical bugs and security issues from code review) os.remove("temp.png") image_url = response['data'][0]['url'] image_filename = wget.download(image_url) @@ -452,7 +429,6 @@ async def chat_assistant(self, ctx, name, *args): run_id=run.id ) -<<<<<<< HEAD current_time = time.time() if current_time - start_time > 60: # TODO: if the assistant times out, deduct from the user's usage, then cancel the run @@ -467,11 +443,7 @@ async def chat_assistant(self, ctx, name, *args): await ctx.send("Error cancelling assistant run") return - if "completed" in run.status: -======= if run.status == "completed": - # await ctx.send("Assistant complete") ->>>>>>> f372db8 (Fix critical bugs and security issues from code review) break elif run.status == "queued": pass diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b7e01c7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,42 @@ +version: '3.8' + +services: + plopbot: + build: + context: . + dockerfile: Dockerfile + image: plopbot:latest + container_name: plopbot + restart: unless-stopped + + # Mount volumes for persistent data + volumes: + - ./soundboard:/app/soundboard + - ./info:/app/info + - ./markov:/app/markov + - ./voices:/app/voices + - ./youtube:/app/youtube + + # Environment variables (optional - can override settings) + # environment: + # - PYTHONUNBUFFERED=1 + + # Network mode (if bot needs to access local network services) + # network_mode: host + + # Logging configuration + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # Resource limits (adjust as needed) + # deploy: + # resources: + # limits: + # cpus: '1.0' + # memory: 1G + # reservations: + # cpus: '0.25' + # memory: 256M