#!/bin/bash # # Library: base.lib # Description: Base Developers Library # Modified: 2024/11/30 15:27:00 # Derechos de Autor (C) [2024] [Mauro Rosero P. ] # # Este programa es software libre: usted puede redistribuirlo y/o modificarlo # bajo los términos de la Licencia Pública Affero General de GNU tal como # lo publica la Free Software Foundation, ya sea la versión 3 de la licencia, # o (a su elección) cualquier versión posterior. # # Este programa se distribuye con la esperanza de que sea útil, # pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de # COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la # Licencia Pública Affero General de GNU para obtener más detalles. # # Debería haber recibido una copia de la Licencia Pública Affero General # junto con este programa. Si no la recibió, consulte . DEVSPATH=${DEVSPATH:=devs} CONFPATH=${CONFPATH:=config} BIN_BASE=${BIN_BASE:=bin} if [ -z "${BIN_HOME}" ]; then BIN_HOME=${HOME}/${DEVSPATH} fi BIN_CONF=${BIN_CONF:=${BIN_BASE}/config} BIN_SOPS=${BIN_SOPS:=${BIN_HOME}/sops} BIN_MESG=${BIN_MESG:=${BIN_BASE}/msg} BIN_LIBS=${BIN_LIBS:=${BIN_BASE}/lib} DEVS_NAME=${CONFPATH}/project.head GIT_IGNORE=.gitignore DEVELOPER_DIR=${HOME}/.developer DATENOW="$(date +"%Y-%m-%d %H:%M:%S")" DATEBAK="$(date +"%Y%m%d%H%M%S")" FREEKV_URL=$(cat < "${BIN_PATH:=${BIN_HOME}}/${CONFPATH}/freekeyval.dat") FREEKV_SOPS_FILE=freekv-sops.devs.yaml DOCKER_LOCAL=dockerfile.local DOCKER_BASE=dockerfile.base DOCKER_SAAS=dockerfile.saas DOCKER_BUILD=build DOCKER_FILE=Dockerfile DOCKER_ENTRY=entrypoint.sh # Verificar si el script se está ejecutando como usuario root (superusuario) function is_root() { if [ "$(id -u)" -eq 0 ]; then return 0 # Es root else return 1 # No es root fi } # Escalar privilegios a superusuario si es necesario # Esta función no ejecuta el script con sudo, solo verifica si tenemos privilegios function check_root_privileges() { if ! is_root; then echo -e "\n${head_info}: Se requieren privilegios de administrador para esta operación." # Verificar si sudo está instalado command -v sudo >/dev/null 2>&1 if [ $? -ne 0 ]; then echo -e "${head_error}: El comando 'sudo' no está instalado. No se pueden escalar privilegios." return 1 fi # Informar que se necesita ejecutar con sudo echo -e "${head_error}: Este script debe ejecutarse con sudo." echo -e "${head_info}: Por favor, ejecute: sudo $0" return 1 fi # Ya es root, no necesita hacer nada return 0 } # Test library function baselib_test() { echo "Base Library loaded!" exit 1 } # Load messages function load_messages() { local BIN_PATH=$1 local MSG_PATH=$2 local LANGUAGE=$3 local MSG_FILE=$4 if [ -f $BIN_PATH/$MSG_PATH/$MSG_FILE.$LANGUAGE ] then source $BIN_PATH/$MSG_PATH/$MSG_FILE.$LANGUAGE else source $BIN_PATH/$MSG_PATH/$MSG_FILE.es fi } # Display developers tools header function display_devstools_header() { local tittle=$1 clear echo "$head_000 $head_002 $tittle" echo "======================================================================" } # Display text header for tui dialog function display_text_header() { local head_text=$1 local subhead_text=$2 clear if [ ! -z "${head_text}" ]; then echo "${head_text}" else echo "$head_000 $head_002" fi if [ ! -z "${subhead_text}" ]; then echo "${subhead_text}" fi echo "======================================================================" } # Display text header apps function display_project_header() { local PROJECT=$1 local tittle=$2 clear echo "$(cat < $PROJECT/config/project.head) $tittle" echo "======================================================================" } # Verify if your program or command is installed function command_installed() { local PROGRAM=$1 if command -v $PROGRAM &> /dev/null; then return 0 fi # No program or command is installed return 1 } # Install os packages function os_pkgs_install() { local PACKAGE=$1 echo "${pkg_install_begin} ${PACKAGE}" if [ "$(uname)" == "Darwin" ]; then # En macOS, a través de Homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install $PACKAGE elif [ -f /etc/debian_version ] || [ -f /etc/os-release ]; then # En sistemas Debian y derivados, a través de apt apt update apt install -y $PACKAGE elif [ -f /etc/redhat-release ]; then # En sistemas Red Hat y derivados, a través de dnf dnf install -y $PACKAGE elif [ -f /etc/arch-release ]; then # En Arch Linux, a través de pacman pacman -Sy --noconfirm $PACKAGE elif [ -f /etc/rc.conf ]; then # En BSD, a través de pkg pkg install -y $PACKAGE else echo "${os_nofound}" exit 1 fi echo "${pkg_install_success} ${PACKAGE}" } # Update or upgrade OS Packages function os_update() { if [ "$(uname)" == "Darwin" ]; then echo "$os_update (BREW)" brew upgrade elif [ -f /etc/debian_version ] || [ -f /etc/os-release ]; then echo "$os_update (APT)" apt update && apt upgrade -y elif [ -f /etc/redhat-release ]; then echo "$os_update (DNF)" dnf update -y elif [ -f /etc/arch-release ]; then echo "$os_update (PACMAN)" pacman -Syu elif [ -f /etc/rc.conf ]; then echo "$os_update (PKG)" pkg update && pkg upgrade else echo "${os_nofound}" exit 1 fi } # Check for container manager installed function container_mode() { command_installed "podman" if [ $? -eq 0 ] then return 0 else command_installed "docker" if [ $? -eq 0 ] then return 1 fi fi # Exit with code 255 if not docker or podman installed return 255 } # Read a file to convert to array # Use global var ARRAY, set to empty before to call this function function read_file_to_array() { local afile="$1" if [[ ! -f "${afile}" ]]; then return 1 fi while IFS= read -r line; do ARRAY+=("${line}") done < "${afile}" return 0 } # Git init repository function git_init() { local REPO_PATH=$1 local BRANCH=$2 git init "$REPO_PATH" -b $BRANCH return $? } # Git add tracked files to repository function git_add_full() { local REPO_PATH=$1 cd $REPO_PATH if [ $? -eq 0 ]; then git add . return $? else return 255 fi } # Git add tracked files to repository function git_commit() { local REPO_PATH=$1 local GIT_MESSAGES=$2 cd $REPO_PATH if [ $? -eq 0 ]; then git commit -m "$GIT_MESSAGES" return $? else return 255 fi } # Git new remote project repository function git_new_project() { local REPO_PATH=$1 local REMOTE_PATH=$2 local GIT_PROJECT=$3 local BRANCH=$4 local REPO_REMOTE=$(printf "$REMOTE_PATH" "${GIT_PROJECT}") echo "$REPO_REMOTE" if [ -d $REPO_PATH ] then cd $REPO_PATH if [ $? -eq 0 ]; then git remote add origin $REPO_REMOTE if [ $? -eq 0 ]; then git checkout $BRANCH if [ $? -eq 0 ]; then git push --set-upstream origin $BRANCH return $? else return 254 fi fi fi fi return 255 } # Git clone repository function git_clone_pull() { local REPO_PATH=$1 local REPO_REMOTE=$2 local APPS=$3 local BRANCH=$4 if [ ! -d $REPO_PATH/$APPS ] then cd $REPO_PATH if [ $? -eq 0 ]; then git clone $REPO_REMOTE -b $BRANCH $APPS return $? else return 255 fi else cd $REPO_PATH/$APPS if [ $? -eq 0 ]; then git pull return $? else return 255 fi fi } # Check for valid os system function get_osname() { if [ "$(uname)" == "Darwin" ]; then # En macOS, instalamos o actualizamos a través de Homebrew os_name=$(sw_vers -productVersion | awk -F '.' '{print "macOS " $1 "." $2}') elif [ -f /etc/debian_version ] || [ -f /etc/os-release ]; then # En sistemas Debian y derivados, instalamos o actualizamos a través de apt os_name=$(grep "^ID_LIKE=" /etc/os-release | cut -d= -f2) if grep -qi "${head_ubuntu}" /etc/os-release then os_name="${head_ubuntu}" fi elif [ -f /etc/redhat-release ]; then # En sistemas Red Hat, instalamos o actualizamos a través de dnf os_name=$(awk '{print $1}' /etc/redhat-release) elif [ -f /etc/arch-release ]; then # En Arch Linux, instalamos o actualizamos a través de pacman os_name=$(grep '^NAME=' /etc/os-release | awk -F '"' '{print $2}') elif [ -f /etc/rc.conf ]; then # En BSD, instalamos o actualizamos a través de pkg os_name=$(awk '{print $2}' /etc/version | awk -F '-' '{print $1}') else os_name="${head_unknow}" fi } # Build container with docker function docker_build() { local CONTAINER=$1 local BASE_IMAGE=$2 docker build ./build -t ${CONTAINER} --build-arg BASE_IMAGE=${BASE_IMAGE} return $? } # Build container with podman function podman_build() { local CONTAINER=$1 local BASE_IMAGE=$2 local registry_path=~/.config/containers if [ ! -d ${registry_path} ] then mkdir ${registry_path} fi echo 'unqualified-search-registries = ["docker.io"]' > "${registry_path}/registries.conf" podman build ./build -t ${CONTAINER} --format docker --build-arg BASE_IMAGE=${BASE_IMAGE} return $? } # Build container with podman or docker function build_container() { local CONTAINER=$1 local BASE_IMAGE=$2 # Verificar si Docker está instalado if command -v docker &> /dev/null then docker_build "$CONTAINER" "$BASE_IMAGE" return $? fi # Verificar si Podman está instalado if command -v podman &> /dev/null then podman_build "$CONTAINER" "$BASE_IMAGE" return $? fi return 1 } # Get sops token for free remote key/value server function sops_freekv_token() { local rc=0 local sops_file="${BIN_SOPS}/${FREEKV_SOPS_FILE}" if [ ! -f "${sops_file}" ]; then return 1 fi token=$(sops -d ${sops_file} | yq .freekv_devs_token) rc=$? if [ $rc -ne 0 ]; then return $rc fi if [ -n "${token}" ]; then return 2 fi echo "${token}" return 0 } # Alias claude code to cortana cortana_alias() { local alias_nombre="cortana" local alias_comando="" local shell_config="" local title="${head_000} ${head_002}" # Determinar la ruta del comando claude if [[ -x "$HOME/.npm-global/bin/claude" ]]; then alias_comando="$HOME/.npm-global/bin/claude" else alias_comando="claude" # Fallback al comando en el PATH fi # Detectar el shell actual y seleccionar el archivo de configuración adecuado case "$SHELL" in */bash) shell_config="$HOME/.bashrc" ;; */zsh) shell_config="$HOME/.zshrc" ;; *) dialog --backtitle "${title}" --title "${head_error}" --msgbox "${npm_040}" 7 50 return 1 ;; esac # Verificar si el alias ya existe en el archivo de configuración if grep -q "alias $alias_nombre=" "$shell_config"; then dialog --backtitle "${title}" --title "${npm_034}" --msgbox "${npm_035} $shell_config" 7 60 return 2 else # Agregar el alias al final del archivo de configuración echo "alias $alias_nombre='$alias_comando'" >> "$shell_config" if [[ $? -eq 0 ]]; then # Recargar el archivo de configuración source "$shell_config" 2>/dev/null || true dialog --backtitle "${title}" --title "${npm_036}" --msgbox "${npm_037} $shell_config\n\n${npm_038}" 9 60 else dialog --backtitle "${title}" --title "${head_error}" --msgbox "${npm_039}" 7 50 return 1 fi fi } # Remove cortana alias remove_cortana_alias() { local alias_nombre="cortana" local shell_config="" local title="${head_000} ${head_002}" # Detectar el shell actual y seleccionar el archivo de configuración adecuado case "$SHELL" in */bash) shell_config="$HOME/.bashrc" ;; */zsh) shell_config="$HOME/.zshrc" ;; *) dialog --backtitle "${title}" --title "${head_error}" --msgbox "${npm_040}" 7 50 return 1 ;; esac # Verificar si el alias existe en el archivo de configuración if grep -q "alias $alias_nombre=" "$shell_config"; then # Eliminar el alias del archivo de configuración sed -i "/alias $alias_nombre=/d" "$shell_config" if [[ $? -eq 0 ]]; then dialog --backtitle "${title}" --title "${npm_041}" --msgbox "${npm_042} $shell_config" 7 60 else dialog --backtitle "${title}" --title "${head_error}" --msgbox "${npm_039}" 7 50 return 1 fi else dialog --backtitle "${title}" --title "${npm_043}" --msgbox "${npm_044}" 7 50 return 2 fi } # Verifica si el sistema está conectado a una VPN # Devuelve 0 si está conectado a una VPN, 1 si no lo está is_connected_to_vpn() { local vpn_interfaces=("tun" "tap" "ppp" "wg" "wireguard" "nordlynx" "mullvad" "proton") local found_vpn=0 # Verificar si existe alguna interfaz VPN activa for vpn_type in "${vpn_interfaces[@]}"; do if ip addr | grep -q "${vpn_type}"; then found_vpn=1 break fi done # Verificar si hay procesos VPN en ejecución if [ $found_vpn -eq 0 ]; then for proc in "openvpn" "wireguard" "wg" "nordvpn" "protonvpn" "pritunl" "anyconnect" "vpnc"; do if pgrep -x "$proc" >/dev/null; then found_vpn=1 break fi done fi # Verificar conexiones de red que puedan indicar VPN if [ $found_vpn -eq 0 ]; then if netstat -rn | grep -q "tun\|tap\|ppp\|wg"; then found_vpn=1 fi fi # Verificar reglas de firewall que puedan indicar VPN if [ $found_vpn -eq 0 ]; then if command -v iptables >/dev/null && iptables -L | grep -qi "vpn\|tunnel"; then found_vpn=1 fi fi if [ $found_vpn -eq 1 ]; then return 0 # Está conectado a una VPN else return 1 # No está conectado a una VPN fi } # Identifica el tipo de VPN al que está conectado el sistema # Devuelve el nombre del tipo de VPN o "Unknown" si no se puede determinar # Si no está conectado a ninguna VPN, devuelve "Not Connected" get_vpn_type() { # Primero verificamos si hay una conexión VPN is_connected_to_vpn if [ $? -ne 0 ]; then echo "" return 1 fi # Mapa de procesos VPN y su tipo correspondiente declare -A vpn_process_map=( ["openvpn"]="OpenVPN" ["pritunl"]="Pritunl" ["pritunl-client"]="Pritunl" ["nordvpnd"]="NordVPN" ["protonvpn"]="ProtonVPN" ["wg-quick"]="WireGuard" ["wg"]="WireGuard" ["mullvad"]="Mullvad" ["expressvpnd"]="ExpressVPN" ["anyconnect"]="Cisco AnyConnect" ["vpnc"]="Cisco VPN" ["openconnect"]="OpenConnect" ["pppd"]="PPTP/L2TP" ["sstp-client"]="SSTP" ["tailscaled"]="Tailscale" ["zerotier-one"]="ZeroTier" ) # Buscar procesos VPN conocidos for proc in "${!vpn_process_map[@]}"; do if pgrep -x "$proc" >/dev/null; then echo "${vpn_process_map[$proc]}" return 0 fi done # Si no encontramos procesos específicos, intentamos identificar por interfaces if ip addr | grep -q "tun"; then # Identificar si es Pritunl (tiene prioridad) if systemctl is-active --quiet pritunl-client.service || pgrep -f "pritunl-client" >/dev/null || ps aux | grep -q "[p]ritunl"; then echo "Pritunl" # Verificar configuración de Pritunl elif [ -d "$HOME/.pritunl" ] || [ -d "/etc/pritunl-client" ]; then echo "Pritunl" # Buscar indicadores adicionales de Pritunl elif grep -q "pritunl" /var/log/syslog 2>/dev/null || grep -q "pritunl" /var/log/messages 2>/dev/null; then echo "Pritunl" # Verificar si es OpenVPN genérico elif ps aux | grep -q "[o]penvpn"; then echo "OpenVPN" else echo "TUN-based VPN" fi return 0 elif ip addr | grep -q "wg"; then echo "WireGuard" return 0 elif ip addr | grep -q "ppp"; then echo "PPP-based VPN" return 0 elif ip addr | grep -q "nordlynx"; then echo "NordVPN (NordLynx)" return 0 elif ip addr | grep -q "proton"; then echo "ProtonVPN" return 0 elif ip addr | grep -q "mullvad"; then echo "Mullvad" return 0 elif ip addr | grep -q "tailscale"; then echo "Tailscale" return 0 elif ip addr | grep -q "zt"; then echo "ZeroTier" return 0 fi # Verificar servicios conocidos de VPN if systemctl is-active --quiet nordvpnd; then echo "NordVPN" return 0 elif systemctl is-active --quiet protonvpn; then echo "ProtonVPN" return 0 elif systemctl is-active --quiet wg-quick@; then echo "WireGuard" return 0 elif systemctl is-active --quiet tailscaled; then echo "Tailscale" return 0 elif systemctl is-active --quiet zerotier-one; then echo "ZeroTier" return 0 fi # Verificar específicamente Pritunl (adicional) if systemctl is-active --quiet pritunl-client.service || [ -d "$HOME/.pritunl" ] || [ -d "/etc/pritunl-client" ]; then echo "Pritunl" return 0 fi # Si llegamos hasta aquí, no pudimos identificar específicamente el tipo de VPN echo "Unknown VPN" return 0 }