#!/bin/bash #Script : ai_token.sh #Apps : MRDEVS TOOLS #Description : Gestiona tokens de proveedores de IA usando SOPS #Author : Sora Rosero One #Generated by : Claude Code (claude-3-7-sonnet-20250219) #Created : 2025/03/21 16:06:20 #Modified : 2025/04/07 07:52:14 #Version : 1.0.0 #Use Notes : # Gestiona múltiples tokens de IA definidos en ai.tokens #============================================================================== # Derechos de Autor [2025] [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 . # Configuración inicial SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BIN_BASE="bin" BIN_LIBS="lib" BIN_MESG="msg" BIN_CFGS="config" BIN_SOPS="sops" # Leer DEVSPATH desde el archivo de configuración o usar "devs" por defecto if [ -f "$SCRIPT_DIR/$BIN_CFGS/devspath.dat" ]; then DEVSPATH=$(cat "$SCRIPT_DIR/$BIN_CFGS/devspath.dat") else DEVSPATH="devs" fi BIN_HOME="$HOME/$DEVSPATH" BIN_PATH=$BIN_HOME/$BIN_BASE VERSION=$(cat "$BIN_HOME/$BIN_BASE/$BIN_CFGS/version") # CHECK SHELL LANGUAGE BIN_LANG=${LANG:0:2} # Importar bibliotecas necesarias source "${BIN_HOME}/${BIN_BASE}/${BIN_LIBS}/base.lib" source "${BIN_HOME}/${BIN_BASE}/${BIN_LIBS}/developers.lib" source "${BIN_HOME}/${BIN_BASE}/${BIN_LIBS}/console.lib" # Cargar mensajes en el idioma del sistema o español por defecto load_messages "${BIN_HOME}/${BIN_BASE}" "${BIN_MESG}" "${BIN_LANG}" "head" load_messages "${BIN_HOME}/${BIN_BASE}" "${BIN_MESG}" "${BIN_LANG}" "developers" apps_title="${aimsg_100}" title="${head_000} ${head_002}" # Comprobar dependencias necesarias check_dependencies() { # Verificar que 'dialog' esté instalado if ! command -v dialog &>/dev/null; then echo "${qrmsg_013}" exit 1 fi # Verificar que 'sops' esté instalado if ! command -v sops &>/dev/null; then dialog_error_box "${head_error}" "${aimsg_115}" exit 1 fi } # Función para cargar la lista de proveedores desde el archivo de configuración load_providers() { local config_file="$BIN_HOME/$BIN_BASE/$BIN_CFGS/ai.tokens" if [ ! -f "$config_file" ]; then echo "${aimsg_111} $config_file" exit 1 fi # Inicializar arrays globales para los proveedores provider_codes=() provider_descs=() # Leer el archivo de configuración y llenar los arrays while IFS=',' read -r provider_code provider_desc enabled active extra; do # Eliminar comillas provider_code=$(echo "$provider_code" | tr -d '"') provider_desc=$(echo "$provider_desc" | tr -d '"') # Agregar a los arrays provider_codes+=("$provider_code") provider_descs+=("$provider_desc") done < <(grep -v "^#" "$config_file") } # Función para leer la ruta personalizada para los tokens desde config get_tokens_path() { local config_file="$BIN_HOME/$BIN_BASE/$BIN_CFGS/ai_tokens.path" local default_path="$BIN_HOME/$BIN_SOPS" if [ -f "$config_file" ]; then # Leer la ruta del archivo de configuración y eliminar espacios/saltos de línea local path_from_config=$(cat "$config_file" | tr -d '\r\n' | tr -d ' ') # Expandir la tilde (~) a la ruta HOME del usuario path_from_config="${path_from_config/#\~/$HOME}" # Verificar que la ruta exista o crearla if [ ! -d "$path_from_config" ]; then mkdir -p "$path_from_config" 2>/dev/null # Si no se pudo crear, usar la ruta por defecto if [ ! -d "$path_from_config" ]; then echo "$default_path" return fi fi echo "$path_from_config" else echo "$default_path" fi } # Función para encriptar token con SOPS encrypt_token() { local provider_code="$1" local token="$2" local tokens_dir=$(get_tokens_path) local output_file="${tokens_dir}/${provider_code}.sops.yaml" local temp_file="/tmp/ai_token_$$" # Crear directorio si no existe mkdir -p "$tokens_dir" # Codificar el token en base64 local token_base64=$(echo -n "$token" | base64) # Crear archivo temporal con token codificado echo "$token_base64" > "$temp_file" # Encriptar usando SOPS if sops --encrypt "$temp_file" > "$output_file"; then # Asegurar permisos adecuados chmod 600 "$output_file" rm -f "$temp_file" return 0 else rm -f "$temp_file" return 1 fi } # Función para mostrar menú de proveedores usando console.lib show_provider_menu() { local options="" local menu_text="" # Construir el menú usando console.lib for i in "${!provider_codes[@]}"; do # Asegurarnos de que la clave sea única if [ -n "$options" ]; then options+="\n" fi options+="${i}:${provider_descs[i]}" # Añadir descripción para el menú if [ -n "$menu_text" ]; then menu_text+="\n" fi menu_text+="${i} ${provider_codes[i]}" done # Mostrar menú usando console.lib choice=$(menu_actions "${aimsg_101}" "$options" 12) # Verificar salida if [ "$choice" == "${head_key_end}" ]; then clear echo "${aimsg_108}" exit 0 fi # Obtener el código y descripción del proveedor seleccionado selected_provider_code="${provider_codes[$choice]}" selected_provider_desc="${provider_descs[$choice]}" return 0 } # Función para solicitar el token al usuario usando console.lib get_token() { local provider_name="$1" local provider_code="$2" while true; do # Usar dialog_input_pass de console.lib dialog_input_pass "${aimsg_102} $provider_name" "${aimsg_103} $provider_code:" "" # Comprobar si el usuario canceló if [ $codex -ne 0 ]; then return 1 fi # Validar token if [ -z "$value" ]; then dialog_error_box "${head_error}" "${aimsg_104}" continue fi # Comprobar longitud del token (debe tener al menos 20 caracteres) if [ ${#value} -lt 20 ]; then dialog_error_box "${head_warning}" "${aimsg_105}" # Preguntar si continuar dialog_yesno "${aimsg_106}" if [ $result -ne 0 ]; then continue fi fi # Token válido break done # Devolver el token echo "$value" return 0 } # Función principal main() { check_dependencies # Cargar proveedores load_providers # Mostrar menú de proveedores show_provider_menu # Ahora tenemos selected_provider_code y selected_provider_desc provider_code="$selected_provider_code" provider_desc="$selected_provider_desc" # Obtener la ruta de tokens y verificar si el archivo ya existe tokens_dir=$(get_tokens_path) sops_file="${tokens_dir}/${provider_code}.sops.yaml" if [ -f "$sops_file" ]; then # Preguntar con dialog_yesno de console.lib dialog_yesno "${aimsg_107}" if [ $result -ne 0 ]; then dialog_error_box "${head_canceled}" "${aimsg_108}" clear exit 0 fi fi # Obtener token get_token "$provider_desc" "$provider_code" if [ $? -ne 0 ]; then dialog_error_box "${head_canceled}" "${aimsg_108}" clear exit 0 fi # Encriptar token if encrypt_token "$provider_code" "$value"; then dialog_error_box "${head_success}" "${aimsg_109} $sops_file" else dialog_error_box "${head_error}" "${aimsg_110}" clear exit 1 fi } # Ejecutar función principal main clear exit 0