485 lines
16 KiB
Bash
Executable File
485 lines
16 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#==============================================================================
|
|
# Animex Extension Server Startup Script
|
|
# Description: Professional startup script with comprehensive error handling,
|
|
# logging, and environment management for Animex Extension Server
|
|
# Author: Animex Developer (Indie)
|
|
# Date: 2023-10-01
|
|
# License: GPL-3.0
|
|
# Version: 2.0
|
|
#==============================================================================
|
|
|
|
set -euo pipefail # Exit on error, undefined vars, pipe failures
|
|
|
|
#==============================================================================
|
|
# CONFIGURATION
|
|
#==============================================================================
|
|
|
|
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
readonly VENV_DIR="${SCRIPT_DIR}/venv"
|
|
readonly REQUIREMENTS="${SCRIPT_DIR}/requirements.txt"
|
|
readonly FIRST_RUN_FLAG="${SCRIPT_DIR}/.first_run_complete"
|
|
readonly LOGO_FILE="${SCRIPT_DIR}/logo.txt"
|
|
readonly LOG_FILE="${SCRIPT_DIR}/startup.log"
|
|
|
|
readonly APP_NAME="Animex Extension Server"
|
|
readonly APP_HOST="${APP_HOST:-0.0.0.0}"
|
|
readonly APP_PORT="${APP_PORT:-7275}"
|
|
readonly PYTHON_CMD="${PYTHON_CMD:-python3}"
|
|
|
|
#==============================================================================
|
|
# UTILITY FUNCTIONS
|
|
#==============================================================================
|
|
|
|
# Logging function with timestamps
|
|
log() {
|
|
local level="$1"
|
|
shift
|
|
local message="$*"
|
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
log_info() { log "INFO" "$@"; }
|
|
log_warn() { log "WARN" "$@"; }
|
|
log_error() { log "ERROR" "$@"; }
|
|
|
|
# Display colored output
|
|
print_colored() {
|
|
local color_code="$1"
|
|
local message="$2"
|
|
echo -e "\033[${color_code}m${message}\033[0m"
|
|
}
|
|
|
|
print_success() { print_colored "1;32" "$1"; }
|
|
print_warning() { print_colored "1;33" "$1"; }
|
|
print_error() { print_colored "1;31" "$1"; }
|
|
print_info() { print_colored "1;36" "$1"; }
|
|
print_orange() { print_colored "1;38;5;208" "$1"; }
|
|
|
|
# Display Animex logo in bright orange
|
|
display_logo() {
|
|
echo ""
|
|
if [[ -f "$LOGO_FILE" ]]; then
|
|
print_orange "$(cat "$LOGO_FILE")"
|
|
echo ""
|
|
print_orange "╔══════════════════════════════════════════════════════════════════════════╗"
|
|
print_orange "║ ANIMEX EXTENSION SERVER ║"
|
|
print_orange "║ Advanced Anime Streaming Platform ║"
|
|
print_orange "╚══════════════════════════════════════════════════════════════════════════╝"
|
|
else
|
|
print_orange "╔══════════════════════════════════════════════════════════════════════════╗"
|
|
print_orange "║ ANIMEX EXTENSION SERVER ║"
|
|
print_orange "║ Advanced Anime Streaming Platform ║"
|
|
print_orange "╚══════════════════════════════════════════════════════════════════════════╝"
|
|
log_warn "Logo file not found: $LOGO_FILE"
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
# Check system requirements
|
|
check_requirements() {
|
|
log_info "Checking system requirements for Animex Extension Server..."
|
|
|
|
if ! command -v "$PYTHON_CMD" &> /dev/null; then
|
|
log_error "Python 3 is not installed or not in PATH"
|
|
print_error "ERROR: $PYTHON_CMD command not found. Please install Python 3."
|
|
exit 1
|
|
fi
|
|
|
|
local python_version
|
|
python_version=$("$PYTHON_CMD" --version 2>&1 | cut -d' ' -f2)
|
|
log_info "Found Python version: $python_version"
|
|
|
|
if ! "$PYTHON_CMD" -m venv --help &> /dev/null; then
|
|
log_error "Python venv module is not available"
|
|
print_error "ERROR: Python venv module not found. Please install python3-venv."
|
|
exit 1
|
|
fi
|
|
|
|
log_info "System requirements check passed for Animex Extension Server"
|
|
}
|
|
|
|
# Create and setup virtual environment
|
|
setup_virtual_environment() {
|
|
log_info "Setting up Animex Extension Server virtual environment at: $VENV_DIR"
|
|
|
|
if [[ ! -d "$VENV_DIR" ]]; then
|
|
print_info "🔧 Creating Animex virtual environment..."
|
|
if ! "$PYTHON_CMD" -m venv "$VENV_DIR"; then
|
|
log_error "Failed to create virtual environment"
|
|
print_error "ERROR: Failed to create virtual environment"
|
|
exit 1
|
|
fi
|
|
log_info "Animex virtual environment created successfully"
|
|
print_success "✓ Animex virtual environment created"
|
|
else
|
|
log_info "Animex virtual environment already exists"
|
|
print_info "🔧 Animex virtual environment already exists"
|
|
fi
|
|
}
|
|
|
|
# Activate virtual environment
|
|
activate_virtual_environment() {
|
|
local activate_script="${VENV_DIR}/bin/activate"
|
|
|
|
if [[ ! -f "$activate_script" ]]; then
|
|
log_error "Virtual environment activation script not found: $activate_script"
|
|
print_error "ERROR: Virtual environment is corrupted. Please delete the venv directory and try again."
|
|
exit 1
|
|
fi
|
|
|
|
# shellcheck source=/dev/null
|
|
source "$activate_script"
|
|
log_info "Animex virtual environment activated"
|
|
print_success "✓ Animex virtual environment activated"
|
|
}
|
|
|
|
#==============================================================================
|
|
# MODULE & EXTENSION REQUIREMENTS MANAGEMENT
|
|
#==============================================================================
|
|
|
|
# Extract requirements from .module files
|
|
extract_module_requirements() {
|
|
local modules_dir="${SCRIPT_DIR}/modules"
|
|
local temp_req_file="$1"
|
|
|
|
if [[ ! -d "$modules_dir" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
while IFS= read -r -d '' module_file; do
|
|
local json_header
|
|
json_header=$(sed -n '2,/^---$/p' "$module_file" | sed '$d' 2>/dev/null)
|
|
|
|
if [[ -n "$json_header" ]]; then
|
|
local requirements
|
|
requirements=$("$PYTHON_CMD" -c "
|
|
import json, sys
|
|
try:
|
|
data = json.loads('''$json_header''')
|
|
reqs = data.get('requirements', [])
|
|
for req in reqs: print(req)
|
|
except: pass
|
|
" 2>/dev/null)
|
|
|
|
if [[ -n "$requirements" ]]; then
|
|
echo "$requirements" >> "$temp_req_file"
|
|
fi
|
|
fi
|
|
done < <(find "$modules_dir" -name "*.module" -type f -print0)
|
|
}
|
|
|
|
# Check and free required ports
|
|
check_and_free_ports() {
|
|
local ports=(7275 7277)
|
|
|
|
for port in "${ports[@]}"; do
|
|
log_info "Checking if port $port is in use..."
|
|
|
|
local pids
|
|
pids=$(lsof -ti tcp:"$port" || true)
|
|
|
|
if [[ -n "$pids" ]]; then
|
|
log_warn "Port $port is already in use by PID(s): $pids"
|
|
print_warning "⚠ Port $port is in use. Attempting to stop process(es)..."
|
|
|
|
# Try graceful shutdown first
|
|
kill $pids 2>/dev/null || true
|
|
sleep 2
|
|
|
|
# Force kill if still alive
|
|
for pid in $pids; do
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
log_warn "PID $pid did not terminate gracefully. Force killing..."
|
|
kill -9 "$pid" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
sleep 1
|
|
fi
|
|
|
|
# Final verification
|
|
if lsof -ti tcp:"$port" &>/dev/null; then
|
|
log_error "Port $port is still in use after kill attempts"
|
|
print_error "❌ Failed to free port $port. Aborting startup."
|
|
exit 1
|
|
else
|
|
log_info "Port $port is free"
|
|
print_success "✓ Port $port is available"
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
# Extract requirements from extension package.json files
|
|
extract_extension_requirements() {
|
|
local extensions_dir="${SCRIPT_DIR}/extensions"
|
|
local temp_req_file="$1"
|
|
|
|
if [[ ! -d "$extensions_dir" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
while IFS= read -r -d '' pkg_file; do
|
|
local requirements
|
|
requirements=$("$PYTHON_CMD" -c "
|
|
import json, sys
|
|
try:
|
|
with open('$pkg_file', 'r') as f:
|
|
data = json.load(f)
|
|
reqs = data.get('requirements', [])
|
|
for req in reqs: print(req)
|
|
except: pass
|
|
" 2>/dev/null)
|
|
|
|
if [[ -n "$requirements" ]]; then
|
|
echo "$requirements" >> "$temp_req_file"
|
|
fi
|
|
done < <(find "$extensions_dir" -name "package.json" -type f -print0)
|
|
}
|
|
|
|
# Install Python dependencies with module and extension requirements
|
|
install_dependencies() {
|
|
local temp_requirements="${SCRIPT_DIR}/.temp_all_requirements.txt"
|
|
|
|
# Clear temp file
|
|
> "$temp_requirements"
|
|
|
|
# Extract requirements from both modules and extensions
|
|
extract_module_requirements "$temp_requirements"
|
|
extract_extension_requirements "$temp_requirements"
|
|
|
|
# Consolidate and count unique requirements
|
|
local final_reqs_count=0
|
|
if [[ -s "$temp_requirements" ]]; then
|
|
sort -u "$temp_requirements" -o "$temp_requirements"
|
|
final_reqs_count=$(wc -l < "$temp_requirements")
|
|
fi
|
|
|
|
# Backup original requirements.txt
|
|
local backup_requirements="${SCRIPT_DIR}/.requirements_backup.txt"
|
|
if [[ -f "$REQUIREMENTS" ]]; then
|
|
cp "$REQUIREMENTS" "$backup_requirements"
|
|
fi
|
|
|
|
# Merge all requirements
|
|
{
|
|
if [[ -f "$backup_requirements" ]]; then
|
|
cat "$backup_requirements"
|
|
fi
|
|
if [[ $final_reqs_count -gt 0 ]]; then
|
|
echo ""
|
|
echo "# Auto-generated module & extension requirements"
|
|
cat "$temp_requirements"
|
|
fi
|
|
} > "$REQUIREMENTS"
|
|
|
|
if [[ $final_reqs_count -gt 0 ]]; then
|
|
log_info "Merged $final_reqs_count unique requirements from modules/extensions."
|
|
print_success "✓ Found and added $final_reqs_count additional requirements."
|
|
fi
|
|
|
|
if [[ ! -f "$REQUIREMENTS" ]]; then
|
|
log_warn "Requirements file not found: $REQUIREMENTS"
|
|
print_warning "WARNING: requirements.txt not found. Server might not run correctly."
|
|
return 0
|
|
fi
|
|
|
|
log_info "Installing/updating dependencies from: $REQUIREMENTS"
|
|
print_info "📦 Installing required packages..."
|
|
|
|
# Upgrade pip first
|
|
pip install --upgrade pip >> "$LOG_FILE" 2>&1
|
|
|
|
# Install all requirements
|
|
if ! pip install -r "$REQUIREMENTS" >> "$LOG_FILE" 2>&1; then
|
|
log_error "Failed to install dependencies. Check $LOG_FILE for details."
|
|
print_error "ERROR: Failed to install packages. Check log file."
|
|
# Restore original requirements before exiting
|
|
if [[ -f "$backup_requirements" ]]; then mv "$backup_requirements" "$REQUIREMENTS"; fi
|
|
rm -f "$temp_requirements"
|
|
deactivate 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
|
|
# Restore original requirements.txt
|
|
if [[ -f "$backup_requirements" ]]; then
|
|
mv "$backup_requirements" "$REQUIREMENTS"
|
|
else
|
|
# If no backup, just clear the generated part
|
|
> "$REQUIREMENTS"
|
|
fi
|
|
rm -f "$temp_requirements"
|
|
|
|
log_info "Dependencies installed successfully"
|
|
print_success "✓ Dependencies installed"
|
|
}
|
|
|
|
# Perform first-time setup
|
|
first_time_setup() {
|
|
print_orange "🚀 Performing Animex Extension Server first-time setup..."
|
|
log_info "Starting Animex Extension Server first-time setup"
|
|
|
|
check_requirements
|
|
setup_virtual_environment
|
|
activate_virtual_environment
|
|
install_dependencies
|
|
|
|
touch "$FIRST_RUN_FLAG"
|
|
log_info "Animex Extension Server first-time setup completed"
|
|
print_success "✓ Animex Extension Server first-time setup completed"
|
|
}
|
|
|
|
# Start the Animex Extension Server
|
|
start_application() {
|
|
log_info "Starting $APP_NAME on http://$APP_HOST:$APP_PORT"
|
|
print_orange "🎬 Starting Animex Extension Server..."
|
|
print_orange "🌐 Server URL: http://$APP_HOST:$APP_PORT"
|
|
print_orange "📺 Animex Extension Server is ready for anime streaming!"
|
|
print_info "Press CTRL+C to stop the Animex server"
|
|
echo ""
|
|
|
|
# Check if uvicorn is available
|
|
if ! command -v uvicorn &> /dev/null; then
|
|
log_error "uvicorn not found in virtual environment"
|
|
print_error "ERROR: uvicorn is not installed. Please check your requirements.txt"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if live reload is enabled
|
|
if [[ "${LIVE_RELOAD:-false}" == "true" ]]; then
|
|
print_info "🔄 Live reload is enabled - server will restart on file changes"
|
|
# Start the server with file watching
|
|
python watch.py
|
|
else
|
|
# Start the server normally
|
|
uvicorn app:app --host "$APP_HOST" --port "$APP_PORT" --log-level info
|
|
fi
|
|
}
|
|
|
|
# Cleanup function
|
|
cleanup() {
|
|
local exit_code=$?
|
|
log_info "Shutting down Animex Extension Server (exit code: $exit_code)"
|
|
|
|
# Clean up any remaining temporary requirement files
|
|
rm -f "${SCRIPT_DIR}/.temp_module_requirements.txt" "${SCRIPT_DIR}/.requirements_backup.txt"
|
|
|
|
if [[ -n "${VIRTUAL_ENV:-}" ]]; then
|
|
deactivate 2>/dev/null || true
|
|
log_info "Animex virtual environment deactivated"
|
|
print_info "🔧 Animex virtual environment deactivated"
|
|
fi
|
|
|
|
print_orange "🛑 Animex Extension Server stopped"
|
|
log_info "Animex Extension Server shutdown complete"
|
|
exit $exit_code
|
|
}
|
|
|
|
# Display help information
|
|
show_help() {
|
|
cat << EOF
|
|
Usage: $0 [OPTIONS]
|
|
|
|
Animex Extension Server - Advanced Anime Streaming Platform
|
|
|
|
OPTIONS:
|
|
-h, --help Show this help message
|
|
--clean Remove virtual environment and start fresh
|
|
--check Check system requirements only
|
|
--live Enable live reload - server will restart on file changes
|
|
--version Show script version
|
|
|
|
ENVIRONMENT VARIABLES:
|
|
APP_HOST Server host (default: 0.0.0.0)
|
|
APP_PORT Server port (default: 7275)
|
|
PYTHON_CMD Python command (default: python3)
|
|
|
|
EXAMPLES:
|
|
$0 Start Animex Extension Server
|
|
$0 --clean Clean install Animex Extension Server
|
|
APP_PORT=8080 $0 Start Animex on port 8080
|
|
|
|
ABOUT ANIMEX:
|
|
Animex Extension Server is an advanced anime streaming platform
|
|
designed to provide seamless anime content delivery and management.
|
|
|
|
EOF
|
|
}
|
|
|
|
#==============================================================================
|
|
# MAIN EXECUTION
|
|
#==============================================================================
|
|
|
|
main() {
|
|
# Parse command line arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
--clean)
|
|
print_info "🧹 Cleaning Animex virtual environment..."
|
|
rm -rf "$VENV_DIR" "$FIRST_RUN_FLAG"
|
|
log_info "Clean install requested - removed Animex venv and first run flag"
|
|
;;
|
|
--check)
|
|
check_requirements
|
|
print_success "✓ Animex system requirements check passed"
|
|
exit 0
|
|
;;
|
|
--live)
|
|
export LIVE_RELOAD=true
|
|
print_info "🔄 Live reload enabled"
|
|
log_info "Live reload feature enabled"
|
|
;;
|
|
--version)
|
|
echo "Animex Extension Server Startup Script v2.0"
|
|
exit 0
|
|
;;
|
|
*)
|
|
print_error "Unknown option: $1"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Set up signal handlers
|
|
trap cleanup EXIT INT TERM
|
|
|
|
# Initialize log file
|
|
echo "=== Animex Extension Server Startup - $(date) ===" >> "$LOG_FILE"
|
|
|
|
# Display Animex logo
|
|
display_logo
|
|
|
|
# Check if this is first run
|
|
if [[ ! -f "$FIRST_RUN_FLAG" ]]; then
|
|
first_time_setup
|
|
else
|
|
print_orange "🎉 Welcome back to Animex Extension Server!"
|
|
log_info "Returning Animex user detected"
|
|
check_requirements
|
|
fi
|
|
|
|
# Activate virtual environment
|
|
activate_virtual_environment
|
|
|
|
# Install/update dependencies
|
|
install_dependencies
|
|
|
|
echo ""
|
|
echo "✅ All systems go! Starting Animex Extension Server... Checking ports..."
|
|
check_and_free_ports
|
|
|
|
# Start the Animex Extension Server
|
|
start_application
|
|
}
|
|
|
|
# Execute main function with all arguments
|
|
main "$@" |