Testing: - Add pytest configuration (pytest.ini) - Add test fixtures (tests/conftest.py) - Add ContentGenerator tests (13 tests) - Add ContentScheduler tests (16 tests) - Add PublisherManager tests (16 tests) - All 45 tests passing Production Docker: - Add docker-compose.prod.yml with healthchecks, resource limits - Add Dockerfile.prod with multi-stage build, non-root user - Add nginx.prod.conf with SSL, rate limiting, security headers - Add .env.prod.example template Maintenance Scripts: - Add backup.sh for database and media backups - Add restore.sh for database restoration - Add cleanup.sh for log rotation and Docker cleanup - Add healthcheck.sh with Telegram alerts Documentation: - Add DEPLOY.md with complete deployment guide Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
95 lines
2.4 KiB
Bash
Executable File
95 lines
2.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# ===========================================
|
|
# Restore Script for Social Media Automation
|
|
# Usage: ./restore.sh [backup_file]
|
|
# ===========================================
|
|
|
|
set -e
|
|
|
|
# Configuration
|
|
BACKUP_DIR="${BACKUP_DIR:-/root/Facebook-X-Threads-Automation/backups}"
|
|
CONTAINER_NAME="${CONTAINER_NAME:-social-automation-db}"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
log() {
|
|
echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
|
}
|
|
|
|
error() {
|
|
log "${RED}ERROR: $1${NC}"
|
|
exit 1
|
|
}
|
|
|
|
success() {
|
|
log "${GREEN}$1${NC}"
|
|
}
|
|
|
|
warning() {
|
|
log "${YELLOW}$1${NC}"
|
|
}
|
|
|
|
# Check if backup file provided
|
|
if [ -z "$1" ]; then
|
|
log "Available database backups:"
|
|
echo ""
|
|
ls -lh "$BACKUP_DIR/database/"*.sql.gz 2>/dev/null || echo " No backups found"
|
|
echo ""
|
|
log "Usage: $0 <backup_file.sql.gz>"
|
|
exit 1
|
|
fi
|
|
|
|
BACKUP_FILE="$1"
|
|
|
|
# Check if file exists
|
|
if [ ! -f "$BACKUP_FILE" ]; then
|
|
# Try with backup dir prefix
|
|
if [ -f "$BACKUP_DIR/database/$BACKUP_FILE" ]; then
|
|
BACKUP_FILE="$BACKUP_DIR/database/$BACKUP_FILE"
|
|
else
|
|
error "Backup file not found: $BACKUP_FILE"
|
|
fi
|
|
fi
|
|
|
|
log "Backup file: $BACKUP_FILE"
|
|
|
|
# Confirm restore
|
|
warning "WARNING: This will overwrite the current database!"
|
|
read -p "Are you sure you want to continue? (yes/no): " CONFIRM
|
|
|
|
if [ "$CONFIRM" != "yes" ]; then
|
|
log "Restore cancelled"
|
|
exit 0
|
|
fi
|
|
|
|
# Check if container is running
|
|
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
error "Database container '$CONTAINER_NAME' is not running"
|
|
fi
|
|
|
|
# Get database credentials
|
|
POSTGRES_USER=$(docker exec $CONTAINER_NAME printenv POSTGRES_USER 2>/dev/null || echo "social_user")
|
|
POSTGRES_DB=$(docker exec $CONTAINER_NAME printenv POSTGRES_DB 2>/dev/null || echo "social_automation")
|
|
|
|
log "Restoring database..."
|
|
|
|
# Drop existing connections and recreate database
|
|
docker exec $CONTAINER_NAME psql -U "$POSTGRES_USER" -c "
|
|
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
|
FROM pg_stat_activity
|
|
WHERE pg_stat_activity.datname = '$POSTGRES_DB'
|
|
AND pid <> pg_backend_pid();" postgres 2>/dev/null || true
|
|
|
|
# Restore
|
|
if gunzip -c "$BACKUP_FILE" | docker exec -i $CONTAINER_NAME psql -U "$POSTGRES_USER" "$POSTGRES_DB"; then
|
|
success "Database restored successfully!"
|
|
else
|
|
error "Database restore failed"
|
|
fi
|
|
|
|
log "Restore completed. Please restart the application containers."
|