initial commit
This commit is contained in:
+17
@@ -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"]
|
||||||
@@ -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/<bot_name>` - 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
|
||||||
@@ -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/<bot_name>', 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/<bot_name>": "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)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Flask==2.3.0
|
||||||
|
Werkzeug==2.3.0
|
||||||
|
gunicorn==21.2.0
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"TestPostsBot": {
|
||||||
|
"version": "0.1",
|
||||||
|
"changelog_url": "https://slfhstd.uk/slfhstd/TestPostsBot/releases"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user