#!/bin/bash # ╔══════════════════════════════════════════════════════════════╗ # ║ lune v1.0.3 ║ # ║ Installateur de projets web Lunekowo ║ # ╚══════════════════════════════════════════════════════════════╝ VERSION="1.0.7" BASE_URL="https://install.lunekkowo.fr" INSTALL_PATH="/usr/local/bin/lune" # Couleurs RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' DIM='\033[2m' NC='\033[0m' # ─── Fonctions utilitaires ─── print_header() { echo "" echo -e "${CYAN}╔══════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║${NC} ${BOLD}lune${NC} v${VERSION} ${CYAN}║${NC}" echo -e "${CYAN}║${NC} ${DIM}Installateur de projets Lunekkowo${NC} ${CYAN}║${NC}" echo -e "${CYAN}╚══════════════════════════════════════════════╝${NC}" echo "" } print_success() { echo -e "${GREEN}✅ $1${NC}" } print_error() { echo -e "${RED}❌ $1${NC}" } print_warning() { echo -e "${YELLOW}⚠️ $1${NC}" } print_info() { echo -e "${BLUE}ℹ️ $1${NC}" } print_step() { echo -e "${CYAN}[+]${NC} $1" } check_root() { if [ "$EUID" -ne 0 ]; then print_error "Veuillez lancer cette commande en tant que root (ajoutez sudo)." exit 1 fi } check_dependencies() { if ! command -v wget &> /dev/null; then print_step "Installation de wget..." apt-get update -y -q && apt-get install -y -q wget fi if ! command -v unzip &> /dev/null; then print_step "Installation de unzip..." apt-get update -y -q && apt-get install -y -q unzip fi } suggest_project() { local SEARCH="$1" # Retirer .zip pour la recherche SEARCH="${SEARCH%.zip}" PROJECTS=$(wget -qO- "${BASE_URL}/list.php" 2>/dev/null) if [ -n "$PROJECTS" ]; then SUGGESTIONS=$(echo "$PROJECTS" | cut -d'|' -f1 | grep -i "$SEARCH") if [ -n "$SUGGESTIONS" ]; then echo "" print_info "Peut-être que vous cherchiez :" echo "$SUGGESTIONS" | while read -r name; do echo -e " ${GREEN}→${NC} ${BOLD}${name%.zip}${NC}" done fi fi } # ─── Commandes ─── show_help() { print_header echo -e "${BOLD}UTILISATION :${NC}" echo " lune Installer un projet" echo "" echo -e "${BOLD}COMMANDES :${NC}" echo " lune -l, --list Lister les projets disponibles" echo " lune -s, --search Rechercher un projet" echo " lune -i, --info Infos sur un projet (taille du zip)" echo " lune -d, --download Télécharger le zip sans extraire" echo " lune -u, --update Mettre à jour lune" echo " lune -v, --version Afficher la version" echo " lune --uninstall Supprimer lune du serveur" echo " lune -h, --help Afficher cette aide" echo "" echo -e "${BOLD}OPTIONS D'INSTALLATION :${NC}" echo " --no-perms Ne pas modifier les permissions" echo " --no-chown Ne pas changer le propriétaire" echo " --owner Propriétaire personnalisé (défaut: www-data:www-data)" echo " --backup Sauvegarder le dossier existant avant d'écraser" echo "" echo -e "${BOLD}EXEMPLES :${NC}" echo " sudo lune monsite /var/www/monsite" echo " sudo lune -d monsite" echo " sudo lune monsite /var/www/monsite --backup --owner apache:apache" echo " sudo lune https://exemple.com/app.zip /var/www/app" echo "" } show_version() { echo -e "lune ${BOLD}v${VERSION}${NC}" } list_projects() { print_header print_step "Récupération de la liste des projets..." echo "" PROJECTS=$(wget -qO- "${BASE_URL}/list.php" 2>/dev/null) if [ -z "$PROJECTS" ]; then print_error "Impossible de récupérer la liste. Le serveur est peut-être hors ligne." exit 1 fi echo -e "${BOLD}📦 Projets disponibles :${NC}" echo -e "${DIM}─────────────────────────────────────────${NC}" echo "$PROJECTS" | while IFS='|' read -r name size; do if [ -n "$name" ]; then printf " ${GREEN}%-30s${NC} ${DIM}%s${NC}\n" "$name" "$size" fi done echo -e "${DIM}─────────────────────────────────────────${NC}" TOTAL=$(echo "$PROJECTS" | grep -c '|') echo -e " ${DIM}Total : ${NC}${BOLD}${TOTAL}${NC}${DIM} projet(s)${NC}" echo "" } search_projects() { local SEARCH_TERM="$1" if [ -z "$SEARCH_TERM" ]; then print_error "Veuillez spécifier un terme de recherche." echo " Utilisation : lune --search " exit 1 fi print_header print_step "Recherche de '${SEARCH_TERM}'..." echo "" PROJECTS=$(wget -qO- "${BASE_URL}/list.php" 2>/dev/null) if [ -z "$PROJECTS" ]; then print_error "Impossible de contacter le serveur." exit 1 fi RESULTS=$(echo "$PROJECTS" | grep -i "$SEARCH_TERM") if [ -z "$RESULTS" ]; then print_warning "Aucun projet trouvé pour '${SEARCH_TERM}'." else echo -e "${BOLD}🔍 Résultats pour '${SEARCH_TERM}' :${NC}" echo -e "${DIM}─────────────────────────────────────────${NC}" echo "$RESULTS" | while IFS='|' read -r name size; do if [ -n "$name" ]; then printf " ${GREEN}%-30s${NC} ${DIM}%s${NC}\n" "$name" "$size" fi done echo -e "${DIM}─────────────────────────────────────────${NC}" fi echo "" } project_info() { local PROJECT="$1" if [ -z "$PROJECT" ]; then print_error "Veuillez spécifier un projet." echo " Utilisation : lune --info " exit 1 fi # Ajouter .zip si nécessaire [[ ! "$PROJECT" =~ \.zip$ ]] && PROJECT="${PROJECT}.zip" print_header print_step "Récupération des infos pour '${PROJECT}'..." # Utiliser HEAD pour obtenir la taille sans télécharger HEADERS=$(wget --spider -qS "${BASE_URL}/projects/${PROJECT}" 2>&1) HTTP_CODE=$(echo "$HEADERS" | grep "HTTP/" | tail -1 | awk '{print $2}') if [ "$HTTP_CODE" != "200" ]; then print_error "Projet '${PROJECT}' introuvable sur le serveur." exit 1 fi SIZE=$(echo "$HEADERS" | grep -i "Content-Length" | awk '{print $2}' | tr -d '\r') LAST_MODIFIED=$(echo "$HEADERS" | grep -i "Last-Modified" | sed 's/.*Last-Modified: //' | tr -d '\r') echo "" echo -e "${BOLD}📋 Informations sur ${PROJECT} :${NC}" echo -e "${DIM}─────────────────────────────────────────${NC}" if [ -n "$SIZE" ]; then if [ "$SIZE" -gt 1048576 ] 2>/dev/null; then SIZE_HR=$(echo "scale=2; $SIZE / 1048576" | bc 2>/dev/null || echo "$SIZE octets") echo -e " Taille : ${BOLD}${SIZE_HR} Mo${NC}" elif [ "$SIZE" -gt 1024 ] 2>/dev/null; then SIZE_HR=$(echo "scale=2; $SIZE / 1024" | bc 2>/dev/null || echo "$SIZE octets") echo -e " Taille : ${BOLD}${SIZE_HR} Ko${NC}" else echo -e " Taille : ${BOLD}${SIZE} octets${NC}" fi fi if [ -n "$LAST_MODIFIED" ]; then echo -e " Modifié le : ${BOLD}${LAST_MODIFIED}${NC}" fi echo -e " URL : ${DIM}${BASE_URL}/projects/${PROJECT}${NC}" echo -e "${DIM}─────────────────────────────────────────${NC}" echo "" } download_only() { local PROJECT="$1" local DEST_DIR="${2:-.}" check_root if [ -z "$PROJECT" ]; then print_error "Veuillez spécifier un projet." echo " Utilisation : lune --download [dossier]" exit 1 fi # Si c'est une URL if [[ "$PROJECT" =~ ^https?:// ]]; then PROJECT_URL="$PROJECT" FILENAME=$(basename "$PROJECT_URL") else [[ ! "$PROJECT" =~ \.zip$ ]] && PROJECT="${PROJECT}.zip" PROJECT_URL="${BASE_URL}/projects/${PROJECT}" FILENAME="$PROJECT" fi print_header print_step "Téléchargement de ${FILENAME}..." mkdir -p "$DEST_DIR" if wget -q --show-progress -O "${DEST_DIR}/${FILENAME}" "$PROJECT_URL"; then print_success "Fichier téléchargé : ${DEST_DIR}/${FILENAME}" else print_error "Impossible de télécharger '${FILENAME}'." rm -f "${DEST_DIR}/${FILENAME}" suggest_project "$FILENAME" exit 1 fi } update_self() { check_root print_header print_step "Vérification des mises à jour..." # Télécharger la dernière version dans un fichier temporaire TMP_FILE=$(mktemp /tmp/lune-update-XXXXXX) if wget -q -O "$TMP_FILE" "${BASE_URL}/installer.sh"; then # Extraire la version du fichier téléchargé REMOTE_VERSION=$(grep '^VERSION=' "$TMP_FILE" | head -1 | cut -d'"' -f2) if [ "$REMOTE_VERSION" = "$VERSION" ]; then print_success "Vous utilisez déjà la dernière version (v${VERSION})." else cp "$TMP_FILE" "$INSTALL_PATH" chmod +x "$INSTALL_PATH" print_success "Mise à jour effectuée : v${VERSION} → v${REMOTE_VERSION}" rm -f "$TMP_FILE" exit 0 fi else print_error "Impossible de contacter le serveur de mise à jour." fi rm -f "$TMP_FILE" } uninstall_self() { check_root print_header print_warning "Désinstallation de lune..." if [ -f "$INSTALL_PATH" ]; then rm -f "$INSTALL_PATH" print_success "lune a été supprimé du serveur. Aucune trace restante." else print_warning "lune n'est pas installé à l'emplacement attendu ($INSTALL_PATH)." fi } # ─── Installation d'un projet ─── install_project() { local PROJECT="$1" shift local DEST_DIR="" local NO_PERMS=false local NO_CHOWN=false local OWNER="www-data:www-data" local BACKUP=false # Parser les arguments restants while [ $# -gt 0 ]; do case "$1" in --no-perms) NO_PERMS=true ;; --no-chown) NO_CHOWN=true ;; --owner) shift OWNER="$1" ;; --backup) BACKUP=true ;; *) if [ -z "$DEST_DIR" ]; then DEST_DIR="$1" fi ;; esac shift done if [ -z "$DEST_DIR" ]; then print_error "Veuillez spécifier un dossier de destination." echo " Utilisation : lune " exit 1 fi check_root check_dependencies # Déterminer l'URL du projet if [[ "$PROJECT" =~ ^https?:// ]]; then PROJECT_URL="$PROJECT" else [[ ! "$PROJECT" =~ \.zip$ ]] && PROJECT="${PROJECT}.zip" PROJECT_URL="${BASE_URL}/projects/${PROJECT}" fi print_header echo -e " ${BOLD}Projet${NC} : $PROJECT_URL" echo -e " ${BOLD}Destination${NC} : $DEST_DIR" [ "$BACKUP" = true ] && echo -e " ${BOLD}Backup${NC} : Oui" [ "$NO_CHOWN" = false ] && echo -e " ${BOLD}Propriétaire${NC}: $OWNER" echo "" # Backup si demandé if [ "$BACKUP" = true ] && [ -d "$DEST_DIR" ]; then BACKUP_NAME="${DEST_DIR}.backup.$(date +%Y%m%d-%H%M%S)" print_step "Sauvegarde de l'existant → ${BACKUP_NAME}" cp -r "$DEST_DIR" "$BACKUP_NAME" fi # Création du dossier print_step "Création du dossier de destination..." mkdir -p "$DEST_DIR" # Téléchargement TMP_ZIP=$(mktemp /tmp/lune-project-XXXXXX.zip) print_step "Téléchargement en cours..." if wget -q --show-progress -O "$TMP_ZIP" "$PROJECT_URL"; then print_step "Extraction..." unzip -q -o "$TMP_ZIP" -d "$DEST_DIR" # Permissions if [ "$NO_PERMS" = false ] && [ "$NO_CHOWN" = false ]; then print_step "Configuration des permissions (${OWNER})..." chown -R "$OWNER" "$DEST_DIR" fi echo "" print_success "Projet installé avec succès dans ${DEST_DIR}" # Afficher le contenu installé echo "" echo -e "${DIM}Contenu installé :${NC}" ls -la "$DEST_DIR" | head -15 TOTAL_FILES=$(find "$DEST_DIR" -type f | wc -l) echo -e "${DIM} ... ${TOTAL_FILES} fichier(s) au total${NC}" else print_error "Impossible de télécharger le projet." suggest_project "$PROJECT" print_info "Tapez 'lune -l' pour voir les projets disponibles." rm -f "$TMP_ZIP" exit 1 fi rm -f "$TMP_ZIP" echo "" } # ─── Point d'entrée ─── if [ $# -eq 0 ]; then show_help exit 0 fi case "$1" in -h|--help) show_help ;; -v|--version) show_version ;; -l|--list) list_projects ;; -s|--search) search_projects "$2" ;; -i|--info) project_info "$2" ;; -d|--download) download_only "$2" "$3" ;; -u|--update) update_self ;; --uninstall) uninstall_self ;; -*) print_error "Option inconnue : $1" echo " Tapez 'lune --help' pour voir les options disponibles." exit 1 ;; *) install_project "$@" ;; esac