From 3e5ae6d5d16c0133454442b8811c9573d4c76105 Mon Sep 17 00:00:00 2001 From: Slfhstd Date: Wed, 11 Mar 2026 19:43:33 +0000 Subject: [PATCH] initial commit --- Dockerfile | 17 ++++++++ README.md | 108 +++++++++++++++++++++++++++++++++++++++++++++++ app.py | 95 +++++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 ++ versions.json | 6 +++ 5 files changed, 229 insertions(+) create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 app.py create mode 100644 requirements.txt create mode 100644 versions.json diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2fca1f8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.11-slim + +WORKDIR /app + +# Copy requirements and install dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application files +COPY app.py . +COPY versions.json . + +# Expose port +EXPOSE 5000 + +# Run the application +CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed467dd --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# Update Server + +Flask-based update server that bots query to check for new versions and send modmail notifications when updates are available. + +## Setup + +### Local Development +1. Install dependencies: + ```bash + pip install -r requirements.txt + ``` + +2. Run the server: + ```bash + python app.py + ``` + The server will run on `http://localhost:5000` + +### Production Deployment + +#### Using Gunicorn +```bash +pip install -r requirements.txt +gunicorn -w 4 -b 0.0.0.0:5000 app:app +``` + +#### Using Docker +```bash +docker build -t update-server . +docker run -p 5000:5000 update-server +``` + +#### Using Docker Compose +From the parent directory: +```bash +docker-compose up update-server +``` + +### Production with Nginx (HTTPS) +Configure nginx as a reverse proxy to handle HTTPS on port 443: + +```nginx +server { + listen 443 ssl http2; + server_name updts.slfhstd.uk; + + ssl_certificate /path/to/cert.pem; + ssl_certificate_key /path/to/key.pem; + + location / { + proxy_pass http://localhost:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +## Managing Versions + +Edit `versions.json` to add, update, or remove bots: + +```json +{ + "TestPostsBot": { + "version": "0.2", + "changelog_url": "https://github.com/yourrepo/releases/tag/v0.2" + }, + "AnotherBot": { + "version": "1.0", + "changelog_url": "https://github.com/yourrepo/AnotherBot/releases" + } +} +``` + +When you update the version here, all connected bots will detect the change and send modmail to their respective subreddits automatically. + +## API Endpoints + +- `GET /` - Server info and available endpoints +- `GET /health` - Health check +- `GET /api/versions` - Get all bot versions +- `GET /api/version/` - Get specific bot version + +Example: +```bash +curl https://updts.slfhstd.uk/api/version/TestPostsBot +``` + +Response: +```json +{ + "version": "0.2", + "changelog_url": "https://github.com/yourrepo/releases/tag/v0.2" +} +``` + +## Logs + +Update check requests are logged to `update_checks.log` with timestamps and bot names. + +## Hosting Options + +- **Heroku** - Easy deployment with free tier +- **Railway.app** - Simple alternative to Heroku +- **DigitalOcean/AWS/GCP** - Full control, more expensive +- **VPS with Nginx** - Most control, requires setup diff --git a/app.py b/app.py new file mode 100644 index 0000000..3d00b95 --- /dev/null +++ b/app.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +""" +Update Server for Bots +Serves version information to bots checking for updates. +""" +from flask import Flask, jsonify, request +import json +import os +from datetime import datetime + +app = Flask(__name__) + +# Load version data from JSON file +VERSIONS_FILE = 'versions.json' +LOG_FILE = 'update_checks.log' + + +def load_versions(): + """Load version info from file.""" + if os.path.exists(VERSIONS_FILE): + try: + with open(VERSIONS_FILE, 'r') as f: + return json.load(f) + except Exception as e: + print(f"Error loading versions.json: {e}") + return {} + return {} + + +def log_check(bot_name): + """Log update check requests.""" + try: + with open(LOG_FILE, 'a') as f: + f.write(f"{datetime.now().isoformat()} - {bot_name}\n") + except Exception as e: + print(f"Error logging check: {e}") + + +@app.route('/api/version/', methods=['GET']) +def get_version(bot_name): + """Get latest version for a specific bot.""" + log_check(bot_name) + versions = load_versions() + + if bot_name in versions: + return jsonify(versions[bot_name]) + + return jsonify({"error": "Bot not found"}), 404 + + +@app.route('/api/versions', methods=['GET']) +def get_all_versions(): + """Get all bot versions.""" + return jsonify(load_versions()) + + +@app.route('/health', methods=['GET']) +def health(): + """Health check endpoint.""" + return jsonify({"status": "ok"}) + + +@app.route('/', methods=['GET']) +def index(): + """Index page with server info.""" + versions = load_versions() + bot_count = len(versions) + return jsonify({ + "service": "Update Server", + "status": "running", + "bots_tracked": bot_count, + "endpoints": { + "/health": "Health check", + "/api/versions": "Get all bot versions", + "/api/version/": "Get specific bot version" + } + }) + + +@app.errorhandler(404) +def not_found(error): + """Handle 404 errors.""" + return jsonify({"error": "Endpoint not found"}), 404 + + +@app.errorhandler(500) +def internal_error(error): + """Handle 500 errors.""" + return jsonify({"error": "Internal server error"}), 500 + + +if __name__ == '__main__': + print("Starting Update Server...") + print(f"Loaded {len(load_versions())} bots from versions.json") + app.run(host='0.0.0.0', port=5000, debug=False) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d8e047d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Flask==2.3.0 +Werkzeug==2.3.0 +gunicorn==21.2.0 diff --git a/versions.json b/versions.json new file mode 100644 index 0000000..7ae2583 --- /dev/null +++ b/versions.json @@ -0,0 +1,6 @@ +{ + "TestPostsBot": { + "version": "0.1", + "changelog_url": "https://slfhstd.uk/slfhstd/TestPostsBot/releases" + } +}