diff --git a/automatizacion_promociones.md b/automatizacion_promociones.md index 507d48c9bb..233da6d8e4 100644 --- a/automatizacion_promociones.md +++ b/automatizacion_promociones.md @@ -1,72 +1,61 @@ # Automatización de Publicación de Promociones para tryonyou.pro -Esta guía explica el funcionamiento de los scripts diseñados para validar, monitorizar y desplegar automáticamente las promociones en el entorno de producción. +Esta guía explica el funcionamiento del script unificado diseñado para validar y desplegar automáticamente las promociones en el entorno de producción de forma desatendida. ## Componentes del sistema -El sistema se compone de varios scripts, todos ellos preparados para operar en español: +El sistema ahora se compone de un único script principal, preparado para operar en español: -1. **`deploy_promotions.py`**: - - Toma el archivo JSON con el contenido de la promoción. - - Valida su estructura asegurando que los campos obligatorios existen. - - Ejecuta la petición HTTP para enviar los datos a la API en producción. - - Soporta un modo `--dry-run` para validar sin realizar la petición de red. +1. **`scripts/daemon_promociones.py`**: + - Funciona como un "daemon" que monitorea periódicamente el directorio `promociones/`. + - Cuando encuentra un archivo JSON con contenido de promoción, valida su estructura asegurando que los campos obligatorios existen (`title`, `description`, `discount_code`, `valid_until`). + - Ejecuta la petición HTTP POST para enviar los datos a la API de producción (`https://api.tryonyou.pro/v1/promotions`). + - Mueve los archivos procesados exitosamente al directorio `promociones_procesadas/` o a `promociones_fallidas/` en caso de error de red o validación. + - Soporta un modo `--dry-run` para probar el flujo completo sin realizar la petición de red real. -2. **`automate_promotions.sh`**: - - Itera a través del directorio `promotions/`. - - Llama a `deploy_promotions.py` para cada archivo JSON. - - Mueve los archivos procesados exitosamente a `promotions_processed/` o a `promotions_failed/` en caso de error. - -3. **`watch_promotions.sh`**: - - Utiliza `inotifywait` para monitorizar continuamente el directorio `promotions/`. - - Cuando se añade o modifica un archivo JSON de promoción, dispara automáticamente `automate_promotions.sh`. +## Cómo usar el sistema -4. **`rutina_desatendida_promociones.sh`**: - - Es el punto de entrada principal para la automatización en background. - - Lanza `watch_promotions.sh` en modo desacoplado (utilizando `nohup`). - - Redirige todas las salidas (logs y errores) al archivo central `promotions.log`. +### Configuración del Despliegue Desatendido (Background) -## Cómo usar el sistema +Para que el script esté permanentemente escuchando y desplegando nuevos archivos que se depositen en la carpeta `promociones/`, ejecuta el daemon en segundo plano: -### Despliegue manual e interactivo +```bash +python3 scripts/daemon_promociones.py > daemon_promociones.log 2>&1 & +``` -Si deseas probar o desplegar un único archivo promocional: +Esto iniciará el proceso en background. El sistema comprobará la carpeta cada 5 segundos. +Puedes monitorizar la actividad revisando el archivo de log: ```bash -./scripts/auto_deploy_promotions.sh +tail -f daemon_promociones.log ``` -Para simularlo sin afectar a la API real, asegúrate de que no esté definida la variable `TRYONYOU_API_KEY` o utiliza explícitamente `--dry-run` donde se soporte. +Para detener el daemon, puedes buscar el PID y matarlo: +```bash +kill $(pgrep -f "daemon_promociones.py") +``` -### Configuración del Despliegue Desatendido (Background) +### Ejecución Única (One-off) -Para que el servidor esté permanentemente escuchando y desplegando nuevos archivos que se depositen en la carpeta `promotions/`, ejecuta: +Si deseas probar o procesar los archivos de promoción actuales en el directorio solo una vez (sin quedarse corriendo): ```bash -./scripts/rutina_desatendida_promociones.sh +python3 scripts/daemon_promociones.py --once ``` -Esto iniciará el proceso en background. El sistema te mostrará un número de proceso (PID). -Puedes monitorizar la actividad revisando el archivo de log: +Para simularlo sin afectar a la API real, añade la bandera `--dry-run`: ```bash -tail -f promotions.log +python3 scripts/daemon_promociones.py --once --dry-run ``` -### Configuración con Cron (Alternativa) - -Si prefieres ejecutar el despliegue de forma periódica en lugar de reaccionar a eventos (inotify), puedes añadir una tarea cron para ejecutar el procesamiento en bloque: +## Directorios y Archivos -1. Abre la configuración de cron: - ```bash - crontab -e - ``` -2. Añade la siguiente línea para que se ejecute cada hora (por ejemplo): - ```cron - 0 * * * * /ruta/absoluta/al/proyecto/scripts/automate_promotions.sh >> /ruta/absoluta/al/proyecto/promotions.log 2>&1 - ``` -*(Nota: Si usas cron, no es necesario ejecutar la rutina desatendida con `watch_promotions.sh`, ya que ambos cumplirían propósitos similares.)* +Al ejecutar el script, automáticamente creará la siguiente estructura si no existe: +- `promociones/` : Directorio donde debes depositar los archivos JSON promocionales nuevos. +- `promociones_procesadas/` : Directorio a donde se mueven los archivos que fueron validados y enviados con éxito. +- `promociones_fallidas/` : Directorio a donde se mueven los archivos con errores de validación o despliegue. ## Variables de Entorno -- **`TRYONYOU_API_KEY`**: Es requerida para realizar peticiones reales a la API de producción. Si no está configurada, los scripts de despliegue operarán o advertirán en modo *dry-run* o simulación. +- **`TRYONYOU_API_KEY`**: Es requerida para realizar peticiones reales a la API de producción. Si no está configurada y no estás en modo `--dry-run`, el script mostrará un error y se detendrá. diff --git a/scripts/auto_deploy_promotions.sh b/scripts/auto_deploy_promotions.sh deleted file mode 100755 index 6d06237e64..0000000000 --- a/scripts/auto_deploy_promotions.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Por defecto a promotion_example.json si no se proporciona argumento -PROMO_FILE="${1:-promotion_example.json}" - -if [ ! -f "$PROMO_FILE" ]; then - echo "Error: No se encontró el archivo de contenido promocional '$PROMO_FILE'." - exit 1 -fi - -# Comprobar si se proporciona clave de API para despliegue desatendido -if [ -z "$TRYONYOU_API_KEY" ]; then - echo "Advertencia: La variable de entorno TRYONYOU_API_KEY no está configurada." - echo "Ejecutando despliegue en modo dry-run para validación..." - DRY_RUN="--dry-run" -else - echo "TRYONYOU_API_KEY está configurada. Procediendo con el despliegue en producción..." - DRY_RUN="" -fi - -# Ejecutar el script de despliegue -echo "Ejecutando despliegue..." -python3 scripts/deploy_promotions.py "$PROMO_FILE" $DRY_RUN - -EXIT_CODE=$? - -if [ $EXIT_CODE -eq 0 ]; then - echo "Rutina completada exitosamente." -else - echo "La rutina falló con código de salida $EXIT_CODE." - exit $EXIT_CODE -fi diff --git a/scripts/auto_deploy_v2.py b/scripts/auto_deploy_v2.py deleted file mode 100755 index e64066dc91..0000000000 --- a/scripts/auto_deploy_v2.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python3 -""" -auto_deploy.py - Automatiza la publicación de promociones para tryonyou.pro. -Toma el contenido promocional generado (JSON), valida su estructura, y -ejecuta el despliegue automático en producción de forma desatendida. - -Uso: - ./auto_deploy.py -""" - -import os -import sys -import json -import urllib.error -import urllib.request - -# Configuración de Producción -API_URL = "https://api.tryonyou.pro/v1/promotions" -REQUIRED_FIELDS = ["title", "description", "discount_code", "valid_until"] - -def main(): - if len(sys.argv) < 2: - print("Uso: ./auto_deploy.py ") - sys.exit(1) - - file_path = sys.argv[1] - - # 1. Leer el archivo - if not os.path.exists(file_path): - print(f"Error: El archivo '{file_path}' no existe.") - sys.exit(1) - - try: - with open(file_path, 'r', encoding='utf-8') as f: - data = json.load(f) - except Exception as e: - print(f"Error leyendo el archivo JSON: {e}") - sys.exit(1) - - # 2. Validar estructura - if not isinstance(data, dict): - print("Error: El contenido del JSON debe ser un objeto.") - sys.exit(1) - - for field in REQUIRED_FIELDS: - if field not in data: - print(f"Error de validación: Falta el campo requerido '{field}'.") - sys.exit(1) - - print("Validación de estructura completada exitosamente.") - - # 3. Ejecutar el despliegue en producción de forma desatendida - # Usamos una variable de entorno para la clave API, o simulamos si no está en un entorno CI - api_key = os.environ.get("TRYONYOU_API_KEY", "default-unattended-key-if-none") - - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {api_key}" - } - - req = urllib.request.Request( - API_URL, - data=json.dumps(data).encode('utf-8'), - headers=headers, - method='POST' - ) - - print(f"Iniciando despliegue desatendido en producción ({API_URL})...") - - try: - response = urllib.request.urlopen(req, timeout=10) - print(f"Despliegue exitoso. Código de respuesta: {response.status}") - except urllib.error.HTTPError as e: - print(f"Error HTTP en el despliegue: {e.code} - {e.reason}") - sys.exit(1) - except urllib.error.URLError as e: - print(f"Fallo de red en el despliegue: {e}") - sys.exit(1) - except Exception as e: - print(f"Error en el despliegue: {e}") - sys.exit(1) - - print("Rutina de despliegue completada.") - -if __name__ == "__main__": - main() diff --git a/scripts/auto_deploy_v2.sh b/scripts/auto_deploy_v2.sh deleted file mode 100755 index 0e0378ef15..0000000000 --- a/scripts/auto_deploy_v2.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -# auto_deploy.sh - Wrapper para ejecutar la rutina de despliegue automático -# de promociones en tryonyou.pro - -if [ -z "$1" ]; then - echo "Uso: ./auto_deploy.sh " - exit 1 -fi - -PROMO_FILE="$1" - -# Ejecutar el script Python que contiene la lógica de validación y despliegue -python3 scripts/auto_deploy_v2.py "$PROMO_FILE" -EXIT_CODE=$? - -if [ $EXIT_CODE -eq 0 ]; then - echo "Despliegue automático completado con éxito." -else - echo "Fallo en el despliegue automático." - exit $EXIT_CODE -fi diff --git a/scripts/automate_promotions.sh b/scripts/automate_promotions.sh deleted file mode 100755 index 23a23e6280..0000000000 --- a/scripts/automate_promotions.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash -# scripts/automate_promotions.sh -# Automatiza la publicación de promociones -# Uso: ./scripts/automate_promotions.sh [--dry-run] - -set -e - -# Directorios de trabajo -BASE_DIR="$(pwd)" -PROMOTIONS_DIR="${BASE_DIR}/promotions" -PROCESSED_DIR="${BASE_DIR}/promotions_processed" -FAILED_DIR="${BASE_DIR}/promotions_failed" - -# Crear directorios si no existen -mkdir -p "$PROMOTIONS_DIR" -mkdir -p "$PROCESSED_DIR" -mkdir -p "$FAILED_DIR" - -# Flags para el script python -PY_ARGS="" -if [ "$1" == "--dry-run" ]; then - PY_ARGS="--dry-run" -fi - -# Iterar sobre todos los archivos JSON en el directorio de promociones -shopt -s nullglob -for file in "$PROMOTIONS_DIR"/*.json; do - echo "Procesando: $file" - - # Ejecutar deploy_promotions.py - if python3 "${BASE_DIR}/scripts/deploy_promotions.py" "$file" $PY_ARGS; then - echo "Éxito: moviendo a $PROCESSED_DIR" - mv "$file" "$PROCESSED_DIR/" - else - echo "Fallo: moviendo a $FAILED_DIR" - mv "$file" "$FAILED_DIR/" - fi -done -shopt -u nullglob - -echo "Procesamiento completado." diff --git a/scripts/rutina_promociones.py b/scripts/daemon_promociones.py similarity index 56% rename from scripts/rutina_promociones.py rename to scripts/daemon_promociones.py index 10983212bb..110ba6b60b 100755 --- a/scripts/rutina_promociones.py +++ b/scripts/daemon_promociones.py @@ -1,10 +1,13 @@ #!/usr/bin/env python3 -# scripts/rutina_promociones.py +# scripts/daemon_promociones.py # Script para automatizar la publicación de promociones de forma desatendida. +# Este script funciona como un daemon (bucle infinito) que monitorea un directorio +# y publica los archivos JSON de promociones en la API. import os import sys import json +import time import shutil import argparse import urllib.error @@ -13,68 +16,51 @@ def validar_promocion(data: Dict[str, Any]) -> bool: - """Valida la estructura de una promoción.""" + """Valida la estructura de una promoción asegurando los campos mínimos.""" campos_requeridos = ["title", "description", "discount_code", "valid_until"] for campo in campos_requeridos: if campo not in data: raise ValueError(f"Falta el campo requerido: {campo}") return True + def desplegar_promocion(data: Dict[str, Any], api_url: str, api_key: str) -> bool: - """Ejecuta el despliegue automático en producción.""" - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {api_key}" - } + """Ejecuta el despliegue automático enviando los datos a la API de producción.""" + headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"} - req = urllib.request.Request(api_url, data=json.dumps(data).encode('utf-8'), headers=headers, method='POST') + req = urllib.request.Request(api_url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST") try: titulo = data.get("title", "Sin título") print(f"Desplegando promoción '{titulo}' en {api_url}...") respuesta = urllib.request.urlopen(req) datos_respuesta = respuesta.read() - print(f"Despliegue exitoso: {datos_respuesta.decode('utf-8') if isinstance(datos_respuesta, bytes) else datos_respuesta}") + + try: + respuesta_texto = datos_respuesta.decode("utf-8") + except UnicodeDecodeError: + respuesta_texto = str(datos_respuesta) + + print(f"Despliegue exitoso: {respuesta_texto}") return True except urllib.error.URLError as e: print(f"Error en el despliegue: {e}") return False -def main() -> None: - parser = argparse.ArgumentParser(description="Automatiza la publicación de promociones para tryonyou.pro") - parser.add_argument("--api-url", default="https://api.tryonyou.pro/v1/promotions", help="URL del Endpoint de la API") - parser.add_argument("--dry-run", action="store_true", help="Simula el despliegue sin hacer la petición HTTP") - args = parser.parse_args() - - directorio_base = os.getcwd() - dir_promociones = os.path.join(directorio_base, "promociones") - dir_procesadas = os.path.join(directorio_base, "promociones_procesadas") - dir_fallidas = os.path.join(directorio_base, "promociones_fallidas") - - # Crear directorios si no existen - for directorio in [dir_promociones, dir_procesadas, dir_fallidas]: - os.makedirs(directorio, exist_ok=True) - - api_key = os.environ.get("TRYONYOU_API_KEY") - if not api_key and not args.dry_run: - print("Error: Falta la variable de entorno TRYONYOU_API_KEY.") - sys.exit(1) - - archivos_procesados = 0 - if not os.path.exists(dir_promociones): - print(f"El directorio '{dir_promociones}' no existe.") - sys.exit(0) +def procesar_archivos( + dir_promociones: str, dir_procesadas: str, dir_fallidas: str, api_url: str, api_key: str, dry_run: bool +) -> None: + """Revisa el directorio por archivos nuevos y los procesa.""" for nombre_archivo in os.listdir(dir_promociones): - if not nombre_archivo.endswith('.json'): + if not nombre_archivo.endswith(".json"): continue ruta_archivo = os.path.join(dir_promociones, nombre_archivo) - print(f"Procesando: {ruta_archivo}") - archivos_procesados += 1 + print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Procesando: {ruta_archivo}") exito = False try: - with open(ruta_archivo, 'r', encoding='utf-8') as f: + with open(ruta_archivo, "r", encoding="utf-8") as f: datos_cargados = json.load(f) if not isinstance(datos_cargados, dict): raise ValueError("El archivo JSON debe contener un diccionario") @@ -83,12 +69,12 @@ def main() -> None: validar_promocion(datos) print("Validación completada con éxito.") - if args.dry_run: + if dry_run: print("Simulando el despliegue (modo dry-run)...") print("Despliegue simulado exitoso.") exito = True else: - exito = desplegar_promocion(datos, args.api_url, api_key or "") + exito = desplegar_promocion(datos, api_url, api_key) except (json.JSONDecodeError, ValueError) as e: print(f"Error al procesar JSON o validar: {e}") @@ -104,10 +90,50 @@ def main() -> None: print(f"Fallo: moviendo a {dir_fallidas}") shutil.move(ruta_archivo, os.path.join(dir_fallidas, nombre_archivo)) - if archivos_procesados == 0: - print(f"No se encontraron archivos JSON en {dir_promociones}.") - print("Rutina de automatización completada.") +def main() -> None: + parser = argparse.ArgumentParser( + description="Daemon para automatizar la publicación desatendida de promociones para tryonyou.pro" + ) + parser.add_argument( + "--api-url", default="https://api.tryonyou.pro/v1/promotions", help="URL del Endpoint de la API" + ) + parser.add_argument("--dry-run", action="store_true", help="Simula el despliegue sin hacer la petición HTTP") + parser.add_argument("--interval", type=int, default=5, help="Intervalo en segundos para revisar el directorio") + parser.add_argument("--once", action="store_true", help="Ejecutar solo una vez en lugar de modo daemon") + args = parser.parse_args() + + directorio_base = os.getcwd() + dir_promociones = os.path.join(directorio_base, "promociones") + dir_procesadas = os.path.join(directorio_base, "promociones_procesadas") + dir_fallidas = os.path.join(directorio_base, "promociones_fallidas") + + # Crear directorios si no existen + for directorio in [dir_promociones, dir_procesadas, dir_fallidas]: + os.makedirs(directorio, exist_ok=True) + + api_key = os.environ.get("TRYONYOU_API_KEY") + if not api_key and not args.dry_run: + print("Error: Falta la variable de entorno TRYONYOU_API_KEY y no se ha especificado --dry-run.") + sys.exit(1) + + print(f"Iniciando daemon de promociones en directorio: {dir_promociones}") + if args.dry_run: + print("Modo DRY RUN activado.") + + if args.once: + procesar_archivos(dir_promociones, dir_procesadas, dir_fallidas, args.api_url, api_key or "", args.dry_run) + print("Ejecución única completada.") + return + + # Bucle infinito (daemon) + try: + while True: + procesar_archivos(dir_promociones, dir_procesadas, dir_fallidas, args.api_url, api_key or "", args.dry_run) + time.sleep(args.interval) + except KeyboardInterrupt: + print("\nDaemon detenido por el usuario.") + if __name__ == "__main__": main() diff --git a/scripts/deploy_promotions.py b/scripts/deploy_promotions.py deleted file mode 100755 index a73f1b2250..0000000000 --- a/scripts/deploy_promotions.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python3 -import os -import sys -import json -import argparse -import urllib.error -import urllib.request -from typing import Any, Dict, cast - - -def validate_promotion(data: Dict[str, Any]) -> bool: - required_fields = ["title", "description", "discount_code", "valid_until"] - for field in required_fields: - if field not in data: - raise ValueError(f"Falta un campo requerido: {field}") - return True - -def deploy_promotion(data: Dict[str, Any], api_url: str, api_key: str) -> bool: - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {api_key}" - } - - req = urllib.request.Request(api_url, data=json.dumps(data).encode('utf-8'), headers=headers, method='POST') - try: - title = data.get("title") - if not isinstance(title, str): - title = str(title) - print(f"Desplegando promoción '{title}' en {api_url}...") - response = urllib.request.urlopen(req) - response_data = response.read() - print(f"Despliegue exitoso: {response_data}") - return True - except urllib.error.URLError as e: - print(f"Error al desplegar: {e}") - return False - -def main() -> None: - parser = argparse.ArgumentParser(description="Desplegar contenido promocional para tryonyou.pro") - parser.add_argument("file", help="Ruta al archivo JSON que contiene el contenido promocional") - parser.add_argument("--api-url", default="https://api.tryonyou.pro/v1/promotions", help="URL del endpoint de la API") - parser.add_argument("--dry-run", action="store_true", help="Simular despliegue sin realizar la petición HTTP") - - args = parser.parse_args() - - if not os.path.exists(args.file): - print(f"Error: El archivo {args.file} no existe.") - sys.exit(1) - - try: - with open(args.file, 'r', encoding='utf-8') as f: - loaded_data = json.load(f) - if not isinstance(loaded_data, dict): - raise ValueError("El archivo JSON debe contener un diccionario") - data = cast(Dict[str, Any], loaded_data) - except (json.JSONDecodeError, ValueError) as e: - print(f"Error al procesar JSON: {e}") - sys.exit(1) - - try: - validate_promotion(data) - print("Validación exitosa.") - except ValueError as e: - print(f"Fallo en la validación: {e}") - sys.exit(1) - - api_key = os.environ.get("TRYONYOU_API_KEY") - if not api_key and not args.dry_run: - print("Error: La variable de entorno TRYONYOU_API_KEY no está configurada.") - sys.exit(1) - - if args.dry_run: - print("Simulando despliegue (modo dry-run)...") - print("Despliegue simulado exitoso.") - else: - if api_key is None: - api_key = "" - success = deploy_promotion(data, args.api_url, api_key) - if not success: - sys.exit(1) - -if __name__ == "__main__": - main() diff --git a/scripts/despliegue_desatendido.py b/scripts/despliegue_desatendido.py deleted file mode 100755 index 736f7ecfb8..0000000000 --- a/scripts/despliegue_desatendido.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python3 -import os -import sys -import json -import shutil -import argparse -import urllib.error -import urllib.request -from typing import Any, Dict - - -def validar_promocion(data: Dict[str, Any]) -> bool: - campos_requeridos = ["title", "description", "discount_code", "valid_until"] - for campo in campos_requeridos: - if campo not in data: - raise ValueError(f"Falta el campo requerido: {campo}") - return True - -def procesar_archivos(directorio_base: str, dry_run: bool) -> None: - dir_promociones = os.path.join(directorio_base, "promotions") - dir_procesados = os.path.join(directorio_base, "promotions_processed") - dir_fallidos = os.path.join(directorio_base, "promotions_failed") - - for directorio in [dir_promociones, dir_procesados, dir_fallidos]: - os.makedirs(directorio, exist_ok=True) - - api_url = "https://api.tryonyou.pro/v1/promotions" - api_key = os.environ.get("TRYONYOU_API_KEY", "") - - if not api_key and not dry_run: - print("Error: La variable de entorno TRYONYOU_API_KEY no está configurada.") - sys.exit(1) - - archivos = [f for f in os.listdir(dir_promociones) if f.endswith(".json")] - if not archivos: - print(f"No se encontraron archivos JSON en {dir_promociones}") - return - - for archivo in archivos: - ruta_archivo = os.path.join(dir_promociones, archivo) - print(f"Procesando archivo: {archivo}") - - try: - with open(ruta_archivo, 'r', encoding='utf-8') as f: - datos = json.load(f) - if not isinstance(datos, dict): - raise ValueError("El archivo JSON debe contener un diccionario") - - validar_promocion(datos) - print("Validación completada.") - - exito = False - if dry_run: - print(f"Simulando despliegue de '{datos.get('title')}' (dry-run)...") - exito = True - else: - print(f"Desplegando promoción '{datos.get('title')}' a {api_url}...") - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {api_key}" - } - req = urllib.request.Request(api_url, data=json.dumps(datos).encode('utf-8'), headers=headers, method='POST') - try: - response = urllib.request.urlopen(req) - print(f"Despliegue exitoso: {response.read()}") - exito = True - except urllib.error.URLError as e: - print(f"Fallo en el despliegue: {e}") - exito = False - - if exito: - shutil.move(ruta_archivo, os.path.join(dir_procesados, archivo)) - print(f"Movido {archivo} a {dir_procesados}") - else: - shutil.move(ruta_archivo, os.path.join(dir_fallidos, archivo)) - print(f"Movido {archivo} a {dir_fallidos}") - - except Exception as e: - print(f"Error procesando {archivo}: {e}") - shutil.move(ruta_archivo, os.path.join(dir_fallidos, archivo)) - print(f"Movido {archivo} a {dir_fallidos}") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Despliegue desatendido de promociones") - parser.add_argument("--dry-run", action="store_true", help="Simular despliegue sin hacer peticiones HTTP") - args = parser.parse_args() - - directorio_base = os.getcwd() - procesar_archivos(directorio_base, args.dry_run) - print("Procesamiento completado.") diff --git a/scripts/rutina_desatendida_promociones.sh b/scripts/rutina_desatendida_promociones.sh deleted file mode 100755 index 943a29635e..0000000000 --- a/scripts/rutina_desatendida_promociones.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -# scripts/rutina_desatendida_promociones.sh -# Inicia la monitorización y despliegue automático de promociones en background. - -BASE_DIR="$(pwd)" -LOG_FILE="${BASE_DIR}/promotions.log" - -echo "Iniciando rutina desatendida de promociones..." -echo "Los registros se guardarán en: $LOG_FILE" - -# Ejecutar el script watch_promotions.sh en background y redirigir la salida al log -nohup "${BASE_DIR}/scripts/watch_promotions.sh" "$@" > "$LOG_FILE" 2>&1 & -PID=$! - -echo "Rutina ejecutándose en background con PID: $PID" diff --git a/scripts/watch_promotions.sh b/scripts/watch_promotions.sh deleted file mode 100755 index 15d58645a3..0000000000 --- a/scripts/watch_promotions.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -# scripts/watch_promotions.sh -# Automatiza la publicación de promociones monitorizando el directorio en busca de nuevos archivos. -# Uso: ./scripts/watch_promotions.sh [--dry-run] - -BASE_DIR="$(pwd)" -PROMOTIONS_DIR="${BASE_DIR}/promotions" - -# Crear directorio si no existe -mkdir -p "$PROMOTIONS_DIR" - -echo "Monitorizando $PROMOTIONS_DIR en busca de nuevos archivos JSON..." - -# Monitorizar continuamente -inotifywait -m -e close_write -e moved_to -q --format '%f' "$PROMOTIONS_DIR" | while read -r filename; do - if [[ "$filename" == *.json ]]; then - echo "Detectado nuevo archivo promocional: $filename" - echo "Ejecutando despliegue..." - "${BASE_DIR}/scripts/automate_promotions.sh" "$@" - echo "Monitorización reanudada..." - fi -done