initial commit
This commit is contained in:
136
scripts/README.md
Normal file
136
scripts/README.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# 🛠️ Scripts de Utilidades
|
||||
|
||||
Este directorio contiene scripts útiles para el desarrollo y mantenimiento del proyecto Balotario.
|
||||
|
||||
## 📁 Scripts Disponibles
|
||||
|
||||
### 🐍 `dev.py`
|
||||
**Script principal de desarrollo en Python**
|
||||
|
||||
#### Comandos:
|
||||
```bash
|
||||
# Limpiar cache y archivos temporales
|
||||
python scripts/dev.py clean
|
||||
|
||||
# Ejecutar todos los tests de Python
|
||||
python scripts/dev.py test
|
||||
|
||||
# Verificar dependencias instaladas
|
||||
python scripts/dev.py deps
|
||||
|
||||
# Iniciar servidor de desarrollo
|
||||
python scripts/dev.py dev
|
||||
|
||||
# Mostrar ayuda
|
||||
python scripts/dev.py help
|
||||
```
|
||||
|
||||
#### Funcionalidades:
|
||||
- ✅ Limpieza automática de `__pycache__` y archivos `.pyc`
|
||||
- ✅ Ejecución de tests de Python
|
||||
- ✅ Verificación de dependencias
|
||||
- ✅ Inicio del servidor de desarrollo
|
||||
- ✅ Ayuda integrada
|
||||
|
||||
### 🧹 `clean.sh`
|
||||
**Script de limpieza rápida en Bash**
|
||||
|
||||
#### Uso:
|
||||
```bash
|
||||
# Ejecutar limpieza completa
|
||||
./scripts/clean.sh
|
||||
|
||||
# O con bash explícito
|
||||
bash scripts/clean.sh
|
||||
```
|
||||
|
||||
#### Funcionalidades:
|
||||
- ✅ Elimina `__pycache__` recursivamente
|
||||
- ✅ Elimina archivos `.pyc`, `.pyo`
|
||||
- ✅ Elimina archivos temporales (`.tmp`, `.temp`, `*~`)
|
||||
- ✅ Elimina archivos del sistema (`.DS_Store`)
|
||||
- ✅ Elimina logs (`.log`)
|
||||
- ✅ Muestra estadísticas del proyecto
|
||||
|
||||
## 🚀 Uso Rápido
|
||||
|
||||
### Desarrollo Diario
|
||||
```bash
|
||||
# 1. Limpiar proyecto
|
||||
./scripts/clean.sh
|
||||
|
||||
# 2. Verificar que todo esté bien
|
||||
python scripts/dev.py test
|
||||
|
||||
# 3. Iniciar desarrollo
|
||||
python scripts/dev.py dev
|
||||
```
|
||||
|
||||
### Antes de Commit
|
||||
```bash
|
||||
# Limpiar y verificar
|
||||
./scripts/clean.sh
|
||||
python scripts/dev.py test
|
||||
```
|
||||
|
||||
### Configuración Inicial
|
||||
```bash
|
||||
# Verificar dependencias
|
||||
python scripts/dev.py deps
|
||||
|
||||
# Si faltan dependencias
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## 🔧 Personalización
|
||||
|
||||
### Agregar Nuevos Comandos a `dev.py`
|
||||
1. Crear nueva función en `dev.py`
|
||||
2. Agregar comando en `main()`
|
||||
3. Documentar en `show_help()`
|
||||
|
||||
### Modificar `clean.sh`
|
||||
- Agregar nuevos patrones de archivos a limpiar
|
||||
- Modificar las estadísticas mostradas
|
||||
- Agregar verificaciones adicionales
|
||||
|
||||
## 📊 Estadísticas
|
||||
|
||||
El script `clean.sh` muestra:
|
||||
- 📁 Directorio actual
|
||||
- 📄 Número de archivos Python
|
||||
- 🌐 Número de archivos HTML
|
||||
- 🎨 Número de archivos CSS
|
||||
- ⚡ Número de archivos JavaScript
|
||||
- 🧪 Número de tests
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Permisos en Linux/macOS
|
||||
```bash
|
||||
# Dar permisos de ejecución
|
||||
chmod +x scripts/clean.sh
|
||||
chmod +x scripts/dev.py
|
||||
```
|
||||
|
||||
### Problemas con Python
|
||||
```bash
|
||||
# Verificar versión de Python
|
||||
python --version
|
||||
|
||||
# Verificar que esté en el entorno virtual
|
||||
which python
|
||||
```
|
||||
|
||||
### Problemas con Bash
|
||||
```bash
|
||||
# Ejecutar con bash explícito
|
||||
bash scripts/clean.sh
|
||||
|
||||
# Verificar sintaxis
|
||||
bash -n scripts/clean.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Nota**: Estos scripts están diseñados para facilitar el desarrollo. Úsalos regularmente para mantener el proyecto limpio y organizado.
|
||||
31
scripts/clean.sh
Executable file
31
scripts/clean.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
# Script de limpieza para el proyecto Balotario
|
||||
|
||||
echo "🧹 Limpiando proyecto Balotario..."
|
||||
|
||||
# Limpiar cache de Python
|
||||
echo "📦 Eliminando __pycache__..."
|
||||
find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name "*.pyc" -delete 2>/dev/null || true
|
||||
find . -name "*.pyo" -delete 2>/dev/null || true
|
||||
|
||||
# Limpiar archivos temporales
|
||||
echo "🗑️ Eliminando archivos temporales..."
|
||||
find . -name "*.tmp" -delete 2>/dev/null || true
|
||||
find . -name "*.temp" -delete 2>/dev/null || true
|
||||
find . -name "*~" -delete 2>/dev/null || true
|
||||
find . -name ".DS_Store" -delete 2>/dev/null || true
|
||||
|
||||
# Limpiar logs
|
||||
echo "📝 Eliminando logs..."
|
||||
find . -name "*.log" -delete 2>/dev/null || true
|
||||
|
||||
echo "✅ Limpieza completada"
|
||||
echo ""
|
||||
echo "📊 Estado del proyecto:"
|
||||
echo " 📁 Directorio principal: $(pwd)"
|
||||
echo " 📄 Archivos Python: $(find . -name "*.py" | wc -l)"
|
||||
echo " 🌐 Archivos HTML: $(find . -name "*.html" | wc -l)"
|
||||
echo " 🎨 Archivos CSS: $(find . -name "*.css" | wc -l)"
|
||||
echo " ⚡ Archivos JS: $(find . -name "*.js" | wc -l)"
|
||||
echo " 🧪 Tests: $(find test/ -name "test_*" | wc -l)"
|
||||
127
scripts/dev.py
Normal file
127
scripts/dev.py
Normal file
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script de utilidades para desarrollo del Balotario
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
def clean_cache():
|
||||
"""Limpiar archivos de cache y temporales"""
|
||||
print("🧹 Limpiando archivos de cache...")
|
||||
|
||||
# Limpiar __pycache__
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for dir_name in dirs:
|
||||
if dir_name == '__pycache__':
|
||||
cache_path = os.path.join(root, dir_name)
|
||||
print(f" Eliminando: {cache_path}")
|
||||
shutil.rmtree(cache_path)
|
||||
|
||||
# Limpiar archivos .pyc
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for file in files:
|
||||
if file.endswith('.pyc'):
|
||||
pyc_path = os.path.join(root, file)
|
||||
print(f" Eliminando: {pyc_path}")
|
||||
os.remove(pyc_path)
|
||||
|
||||
print("✅ Cache limpiado")
|
||||
|
||||
def run_tests():
|
||||
"""Ejecutar todos los tests de Python"""
|
||||
print("🧪 Ejecutando tests de Python...")
|
||||
|
||||
test_files = [
|
||||
'test/test_parser.py',
|
||||
'test/test_clean_parser.py'
|
||||
]
|
||||
|
||||
for test_file in test_files:
|
||||
if os.path.exists(test_file):
|
||||
print(f"\n📝 Ejecutando: {test_file}")
|
||||
try:
|
||||
subprocess.run([sys.executable, test_file], check=True)
|
||||
print(f"✅ {test_file} - PASÓ")
|
||||
except subprocess.CalledProcessError:
|
||||
print(f"❌ {test_file} - FALLÓ")
|
||||
else:
|
||||
print(f"⚠️ {test_file} - NO ENCONTRADO")
|
||||
|
||||
def check_dependencies():
|
||||
"""Verificar que las dependencias estén instaladas"""
|
||||
print("📦 Verificando dependencias...")
|
||||
|
||||
try:
|
||||
import flask
|
||||
print(f"✅ Flask {flask.__version__}")
|
||||
except ImportError:
|
||||
print("❌ Flask no instalado")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def start_dev_server():
|
||||
"""Iniciar servidor de desarrollo"""
|
||||
print("🚀 Iniciando servidor de desarrollo...")
|
||||
|
||||
if not check_dependencies():
|
||||
print("❌ Faltan dependencias. Ejecuta: pip install -r requirements.txt")
|
||||
return
|
||||
|
||||
# Configurar variables de entorno para desarrollo
|
||||
os.environ['FLASK_ENV'] = 'development'
|
||||
os.environ['FLASK_DEBUG'] = 'true'
|
||||
|
||||
try:
|
||||
subprocess.run([sys.executable, 'run.py'])
|
||||
except KeyboardInterrupt:
|
||||
print("\n👋 Servidor detenido")
|
||||
|
||||
def show_help():
|
||||
"""Mostrar ayuda"""
|
||||
print("""
|
||||
🛠️ Script de Utilidades - Balotario Licencia A-I
|
||||
|
||||
Comandos disponibles:
|
||||
clean - Limpiar archivos de cache y temporales
|
||||
test - Ejecutar todos los tests de Python
|
||||
deps - Verificar dependencias instaladas
|
||||
dev - Iniciar servidor de desarrollo
|
||||
help - Mostrar esta ayuda
|
||||
|
||||
Uso:
|
||||
python scripts/dev.py <comando>
|
||||
|
||||
Ejemplos:
|
||||
python scripts/dev.py clean
|
||||
python scripts/dev.py test
|
||||
python scripts/dev.py dev
|
||||
""")
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
show_help()
|
||||
return
|
||||
|
||||
command = sys.argv[1].lower()
|
||||
|
||||
if command == 'clean':
|
||||
clean_cache()
|
||||
elif command == 'test':
|
||||
run_tests()
|
||||
elif command == 'deps':
|
||||
check_dependencies()
|
||||
elif command == 'dev':
|
||||
start_dev_server()
|
||||
elif command == 'help':
|
||||
show_help()
|
||||
else:
|
||||
print(f"❌ Comando desconocido: {command}")
|
||||
show_help()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
192
scripts/docker.sh
Executable file
192
scripts/docker.sh
Executable file
@@ -0,0 +1,192 @@
|
||||
#!/bin/bash
|
||||
# Scripts de utilidades para Docker
|
||||
|
||||
set -e
|
||||
|
||||
# Colores para output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Funciones de utilidad
|
||||
log_info() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# Función para construir la imagen
|
||||
build() {
|
||||
log_info "Construyendo imagen Docker..."
|
||||
docker build -t balotario:latest .
|
||||
log_success "Imagen construida exitosamente"
|
||||
}
|
||||
|
||||
# Función para ejecutar en desarrollo
|
||||
dev() {
|
||||
log_info "Iniciando contenedor en modo desarrollo..."
|
||||
docker run -it --rm \
|
||||
-p 5000:5000 \
|
||||
-v $(pwd):/app \
|
||||
-e FLASK_ENV=development \
|
||||
-e FLASK_DEBUG=true \
|
||||
-e DOCKER_CONTAINER=true \
|
||||
--name balotario-dev \
|
||||
balotario:latest
|
||||
}
|
||||
|
||||
# Función para ejecutar en producción
|
||||
prod() {
|
||||
log_info "Iniciando contenedor en modo producción..."
|
||||
docker run -d \
|
||||
-p 5000:5000 \
|
||||
-e FLASK_ENV=production \
|
||||
-e FLASK_DEBUG=false \
|
||||
-e DOCKER_CONTAINER=true \
|
||||
--name balotario-prod \
|
||||
--restart unless-stopped \
|
||||
balotario:latest
|
||||
log_success "Contenedor iniciado en modo producción"
|
||||
log_info "Accede a: http://localhost:5000"
|
||||
}
|
||||
|
||||
# Función para usar Docker Compose
|
||||
compose_up() {
|
||||
log_info "Iniciando servicios con Docker Compose..."
|
||||
docker-compose up -d
|
||||
log_success "Servicios iniciados"
|
||||
log_info "Aplicación: http://localhost:5000"
|
||||
log_info "Nginx: http://localhost:80"
|
||||
}
|
||||
|
||||
# Función para detener Docker Compose
|
||||
compose_down() {
|
||||
log_info "Deteniendo servicios..."
|
||||
docker-compose down
|
||||
log_success "Servicios detenidos"
|
||||
}
|
||||
|
||||
# Función para ver logs
|
||||
logs() {
|
||||
local service=${1:-balotario}
|
||||
log_info "Mostrando logs de $service..."
|
||||
docker-compose logs -f $service
|
||||
}
|
||||
|
||||
# Función para limpiar contenedores e imágenes
|
||||
clean() {
|
||||
log_warning "Limpiando contenedores e imágenes..."
|
||||
|
||||
# Detener contenedores
|
||||
docker stop balotario-dev balotario-prod 2>/dev/null || true
|
||||
docker rm balotario-dev balotario-prod 2>/dev/null || true
|
||||
|
||||
# Limpiar con docker-compose
|
||||
docker-compose down --rmi all --volumes --remove-orphans 2>/dev/null || true
|
||||
|
||||
# Limpiar imágenes huérfanas
|
||||
docker image prune -f
|
||||
|
||||
log_success "Limpieza completada"
|
||||
}
|
||||
|
||||
# Función para mostrar estado
|
||||
status() {
|
||||
log_info "Estado de contenedores:"
|
||||
docker ps -a --filter "name=balotario"
|
||||
|
||||
echo ""
|
||||
log_info "Estado de servicios Docker Compose:"
|
||||
docker-compose ps
|
||||
}
|
||||
|
||||
# Función para entrar al contenedor
|
||||
shell() {
|
||||
local container=${1:-balotario-prod}
|
||||
log_info "Entrando al contenedor $container..."
|
||||
docker exec -it $container /bin/bash
|
||||
}
|
||||
|
||||
# Función de ayuda
|
||||
help() {
|
||||
echo "🐳 Scripts de Docker para Balotario"
|
||||
echo ""
|
||||
echo "Uso: $0 <comando>"
|
||||
echo ""
|
||||
echo "Comandos disponibles:"
|
||||
echo " build - Construir imagen Docker"
|
||||
echo " dev - Ejecutar en modo desarrollo"
|
||||
echo " prod - Ejecutar en modo producción"
|
||||
echo " compose-up - Iniciar con Docker Compose"
|
||||
echo " compose-down - Detener Docker Compose"
|
||||
echo " logs [service]- Ver logs (default: balotario)"
|
||||
echo " clean - Limpiar contenedores e imágenes"
|
||||
echo " status - Mostrar estado de contenedores"
|
||||
echo " shell [name] - Entrar al contenedor"
|
||||
echo " help - Mostrar esta ayuda"
|
||||
echo ""
|
||||
echo "Ejemplos:"
|
||||
echo " $0 build"
|
||||
echo " $0 compose-up"
|
||||
echo " $0 logs nginx"
|
||||
echo " $0 shell balotario-prod"
|
||||
}
|
||||
|
||||
# Función principal
|
||||
main() {
|
||||
case "${1:-help}" in
|
||||
build)
|
||||
build
|
||||
;;
|
||||
dev)
|
||||
build
|
||||
dev
|
||||
;;
|
||||
prod)
|
||||
build
|
||||
prod
|
||||
;;
|
||||
compose-up)
|
||||
compose_up
|
||||
;;
|
||||
compose-down)
|
||||
compose_down
|
||||
;;
|
||||
logs)
|
||||
logs $2
|
||||
;;
|
||||
clean)
|
||||
clean
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
shell)
|
||||
shell $2
|
||||
;;
|
||||
help|*)
|
||||
help
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Verificar que Docker esté instalado
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker no está instalado"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ejecutar función principal
|
||||
main "$@"
|
||||
156
scripts/download_images.py
Normal file
156
scripts/download_images.py
Normal file
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script to download all images from the MTC website and store them locally.
|
||||
This makes the application work completely offline.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
from urllib.parse import urlparse
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
def create_images_directory():
|
||||
"""Create the static/images directory if it doesn't exist."""
|
||||
images_dir = Path("static/images")
|
||||
images_dir.mkdir(parents=True, exist_ok=True)
|
||||
return images_dir
|
||||
|
||||
def extract_image_urls_from_markdown():
|
||||
"""Extract all image URLs from the markdown file."""
|
||||
markdown_file = Path("data/balotario_clase_a_cat_I.md")
|
||||
|
||||
if not markdown_file.exists():
|
||||
print(f"Error: {markdown_file} not found!")
|
||||
return []
|
||||
|
||||
with open(markdown_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find all image URLs
|
||||
pattern = r'!\[\]\((https://sierdgtt\.mtc\.gob\.pe/Content/img-data/img\d+\.jpg)\)'
|
||||
urls = re.findall(pattern, content)
|
||||
|
||||
return list(set(urls)) # Remove duplicates
|
||||
|
||||
def download_image(url, images_dir, retries=3):
|
||||
"""Download a single image with retry logic."""
|
||||
try:
|
||||
# Extract filename from URL
|
||||
filename = os.path.basename(urlparse(url).path)
|
||||
filepath = images_dir / filename
|
||||
|
||||
# Skip if already exists
|
||||
if filepath.exists():
|
||||
print(f"✓ {filename} already exists")
|
||||
return True
|
||||
|
||||
print(f"📥 Downloading {filename}...")
|
||||
|
||||
# Download with retries
|
||||
for attempt in range(retries):
|
||||
try:
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
||||
}
|
||||
|
||||
response = requests.get(url, headers=headers, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
# Save the image
|
||||
with open(filepath, 'wb') as f:
|
||||
f.write(response.content)
|
||||
|
||||
print(f"✅ Downloaded {filename} ({len(response.content)} bytes)")
|
||||
return True
|
||||
|
||||
except requests.RequestException as e:
|
||||
print(f"❌ Attempt {attempt + 1} failed for {filename}: {e}")
|
||||
if attempt < retries - 1:
|
||||
time.sleep(2) # Wait before retry
|
||||
|
||||
print(f"💥 Failed to download {filename} after {retries} attempts")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"💥 Error downloading {url}: {e}")
|
||||
return False
|
||||
|
||||
def update_markdown_file(images_dir):
|
||||
"""Update the markdown file to use local image paths."""
|
||||
markdown_file = Path("data/balotario_clase_a_cat_I.md")
|
||||
backup_file = Path("data/balotario_clase_a_cat_I.md.backup")
|
||||
|
||||
# Create backup
|
||||
if not backup_file.exists():
|
||||
with open(markdown_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
with open(backup_file, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f"📋 Created backup: {backup_file}")
|
||||
|
||||
# Read current content
|
||||
with open(markdown_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Replace URLs with local paths
|
||||
pattern = r'!\[\]\(https://sierdgtt\.mtc\.gob\.pe/Content/img-data/(img\d+\.jpg)\)'
|
||||
replacement = r''
|
||||
|
||||
updated_content = re.sub(pattern, replacement, content)
|
||||
|
||||
# Write updated content
|
||||
with open(markdown_file, 'w', encoding='utf-8') as f:
|
||||
f.write(updated_content)
|
||||
|
||||
print("📝 Updated markdown file to use local image paths")
|
||||
|
||||
def main():
|
||||
"""Main function to download all images."""
|
||||
print("🚀 Starting image download process...")
|
||||
|
||||
# Create images directory
|
||||
images_dir = create_images_directory()
|
||||
print(f"📁 Images will be saved to: {images_dir}")
|
||||
|
||||
# Extract image URLs
|
||||
urls = extract_image_urls_from_markdown()
|
||||
print(f"🔍 Found {len(urls)} unique images to download")
|
||||
|
||||
if not urls:
|
||||
print("❌ No image URLs found!")
|
||||
return
|
||||
|
||||
# Download images
|
||||
successful = 0
|
||||
failed = 0
|
||||
|
||||
for i, url in enumerate(urls, 1):
|
||||
print(f"\n[{i}/{len(urls)}] Processing: {url}")
|
||||
|
||||
if download_image(url, images_dir):
|
||||
successful += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
# Small delay to be respectful to the server
|
||||
time.sleep(0.5)
|
||||
|
||||
# Summary
|
||||
print(f"\n📊 Download Summary:")
|
||||
print(f"✅ Successful: {successful}")
|
||||
print(f"❌ Failed: {failed}")
|
||||
print(f"📁 Total files: {len(list(images_dir.glob('*.jpg')))}")
|
||||
|
||||
# Update markdown file
|
||||
if successful > 0:
|
||||
print(f"\n🔄 Updating markdown file...")
|
||||
update_markdown_file(images_dir)
|
||||
print(f"✅ Process completed!")
|
||||
print(f"💡 You can now run your app completely offline!")
|
||||
else:
|
||||
print(f"❌ No images were downloaded successfully")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
288
scripts/env-setup.bat
Normal file
288
scripts/env-setup.bat
Normal file
@@ -0,0 +1,288 @@
|
||||
@echo off
|
||||
REM ====================================
|
||||
REM SCRIPT DE CONFIGURACIÓN DE ENTORNO
|
||||
REM Balotario Licencia A-I (Windows)
|
||||
REM =============================
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Función para generar SECRET_KEY
|
||||
:generate_secret_key
|
||||
python -c "import secrets; print(secrets.token_hex(32))" 2>nul
|
||||
if errorlevel 1 (
|
||||
REM Fallback si Python no está disponible
|
||||
echo %RANDOM%%RANDOM%%RANDOM%%RANDOM%
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM Función para mostrar header
|
||||
:print_header
|
||||
echo ======================================
|
||||
echo 🌍 CONFIGURACIÓN DE ENTORNO
|
||||
echo Balotario Licencia A-I
|
||||
echo ======================================
|
||||
echo.
|
||||
goto :eof
|
||||
|
||||
REM Función para configurar desarrollo
|
||||
:setup_development
|
||||
echo ℹ️ Configurando entorno de desarrollo...
|
||||
|
||||
REM Generar SECRET_KEY
|
||||
for /f %%i in ('python -c "import secrets; print(secrets.token_hex(32))" 2^>nul') do set SECRET_KEY=%%i
|
||||
if "!SECRET_KEY!"=="" set SECRET_KEY=%RANDOM%%RANDOM%%RANDOM%%RANDOM%
|
||||
|
||||
REM Crear archivo .env
|
||||
(
|
||||
echo # ====================================
|
||||
echo # CONFIGURACIÓN DE DESARROLLO
|
||||
echo # Generado automáticamente: %date% %time%
|
||||
echo # ====================================
|
||||
echo.
|
||||
echo # Configuración de Flask
|
||||
echo SECRET_KEY=!SECRET_KEY!
|
||||
echo FLASK_ENV=development
|
||||
echo FLASK_CONFIG=development
|
||||
echo FLASK_DEBUG=true
|
||||
echo.
|
||||
echo # Configuración del servidor
|
||||
echo HOST=127.0.0.1
|
||||
echo PORT=5000
|
||||
echo.
|
||||
echo # Configuración de Docker
|
||||
echo DOCKER_CONTAINER=false
|
||||
echo.
|
||||
echo # Configuración de logging
|
||||
echo LOG_LEVEL=DEBUG
|
||||
echo AUTO_RELOAD=true
|
||||
echo SHOW_DEBUG_TOOLBAR=false
|
||||
echo.
|
||||
echo # ====================================
|
||||
echo # NOTAS:
|
||||
echo # - Cambia SECRET_KEY antes de ir a producción
|
||||
echo # - Revisa .env.sample para más opciones
|
||||
echo # ====================================
|
||||
) > .env
|
||||
|
||||
echo ✅ Configuración de desarrollo creada en .env
|
||||
goto :eof
|
||||
|
||||
REM Función para configurar producción
|
||||
:setup_production
|
||||
echo ℹ️ Configurando entorno de producción...
|
||||
|
||||
REM Generar SECRET_KEY
|
||||
for /f %%i in ('python -c "import secrets; print(secrets.token_hex(32))" 2^>nul') do set SECRET_KEY=%%i
|
||||
if "!SECRET_KEY!"=="" set SECRET_KEY=%RANDOM%%RANDOM%%RANDOM%%RANDOM%
|
||||
|
||||
REM Crear archivo .env
|
||||
(
|
||||
echo # ====================================
|
||||
echo # CONFIGURACIÓN DE PRODUCCIÓN
|
||||
echo # Generado automáticamente: %date% %time%
|
||||
echo # ====================================
|
||||
echo.
|
||||
echo # Configuración de Flask
|
||||
echo SECRET_KEY=!SECRET_KEY!
|
||||
echo FLASK_ENV=production
|
||||
echo FLASK_CONFIG=production
|
||||
echo FLASK_DEBUG=false
|
||||
echo.
|
||||
echo # Configuración del servidor
|
||||
echo HOST=0.0.0.0
|
||||
echo PORT=5000
|
||||
echo.
|
||||
echo # Configuración de Docker
|
||||
echo DOCKER_CONTAINER=true
|
||||
echo.
|
||||
echo # Configuración de logging
|
||||
echo LOG_LEVEL=INFO
|
||||
echo.
|
||||
echo # ====================================
|
||||
echo # IMPORTANTE:
|
||||
echo # - Guarda SECRET_KEY en lugar seguro
|
||||
echo # - Revisa todas las configuraciones antes de desplegar
|
||||
echo # ====================================
|
||||
) > .env
|
||||
|
||||
echo ✅ Configuración de producción creada en .env
|
||||
echo ⚠️ IMPORTANTE: Guarda la SECRET_KEY en un lugar seguro
|
||||
goto :eof
|
||||
|
||||
REM Función para configurar Docker
|
||||
:setup_docker
|
||||
echo ℹ️ Configurando entorno para Docker...
|
||||
|
||||
REM Generar SECRET_KEY
|
||||
for /f %%i in ('python -c "import secrets; print(secrets.token_hex(32))" 2^>nul') do set SECRET_KEY=%%i
|
||||
if "!SECRET_KEY!"=="" set SECRET_KEY=%RANDOM%%RANDOM%%RANDOM%%RANDOM%
|
||||
|
||||
REM Crear archivo .env
|
||||
(
|
||||
echo # ====================================
|
||||
echo # CONFIGURACIÓN PARA DOCKER
|
||||
echo # Generado automáticamente: %date% %time%
|
||||
echo # ====================================
|
||||
echo.
|
||||
echo # Configuración de Flask
|
||||
echo SECRET_KEY=!SECRET_KEY!
|
||||
echo FLASK_ENV=production
|
||||
echo FLASK_CONFIG=production
|
||||
echo FLASK_DEBUG=false
|
||||
echo.
|
||||
echo # Configuración del servidor
|
||||
echo HOST=0.0.0.0
|
||||
echo PORT=5000
|
||||
echo.
|
||||
echo # Configuración de Docker
|
||||
echo DOCKER_CONTAINER=true
|
||||
echo.
|
||||
echo # Configuración de logging
|
||||
echo LOG_LEVEL=INFO
|
||||
echo.
|
||||
echo # ====================================
|
||||
echo # DOCKER NOTES:
|
||||
echo # - Estas variables pueden ser sobrescritas en docker-compose.yml
|
||||
echo # - Para desarrollo con Docker, cambia FLASK_ENV=development
|
||||
echo # ====================================
|
||||
) > .env
|
||||
|
||||
echo ✅ Configuración para Docker creada en .env
|
||||
goto :eof
|
||||
|
||||
REM Función para validar configuración
|
||||
:validate_env
|
||||
echo ℹ️ Validando configuración...
|
||||
|
||||
if not exist ".env" (
|
||||
echo ❌ Archivo .env no encontrado
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
findstr /C:"SECRET_KEY=" .env >nul
|
||||
if errorlevel 1 (
|
||||
echo ❌ SECRET_KEY no encontrada en .env
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
findstr /C:"FLASK_ENV=" .env >nul
|
||||
if errorlevel 1 (
|
||||
echo ❌ FLASK_ENV no encontrada en .env
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo ✅ Configuración válida
|
||||
echo.
|
||||
echo ℹ️ Resumen de configuración:
|
||||
echo ------------------------
|
||||
for /f "tokens=1,2 delims==" %%a in ('findstr /R "^SECRET_KEY= ^FLASK_ENV= ^FLASK_DEBUG= ^HOST= ^PORT=" .env') do (
|
||||
if "%%a"=="SECRET_KEY" (
|
||||
echo %%a=***OCULTA***
|
||||
) else (
|
||||
echo %%a=%%b
|
||||
)
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM Función para mostrar ayuda
|
||||
:show_help
|
||||
echo Uso: %~nx0 [COMANDO]
|
||||
echo.
|
||||
echo Comandos disponibles:
|
||||
echo dev Configurar para desarrollo local
|
||||
echo prod Configurar para producción
|
||||
echo docker Configurar para Docker
|
||||
echo validate Validar configuración actual
|
||||
echo backup Crear backup de .env actual
|
||||
echo restore Restaurar desde .env.sample
|
||||
echo help Mostrar esta ayuda
|
||||
echo.
|
||||
echo Ejemplos:
|
||||
echo %~nx0 dev # Configuración de desarrollo
|
||||
echo %~nx0 prod # Configuración de producción
|
||||
echo %~nx0 docker # Configuración para Docker
|
||||
goto :eof
|
||||
|
||||
REM Función para crear backup
|
||||
:backup_env
|
||||
if exist ".env" (
|
||||
set backup_file=.env.backup.%date:~-4%%date:~3,2%%date:~0,2%_%time:~0,2%%time:~3,2%%time:~6,2%
|
||||
set backup_file=!backup_file: =0!
|
||||
copy .env "!backup_file!" >nul
|
||||
echo ✅ Backup creado: !backup_file!
|
||||
) else (
|
||||
echo ⚠️ No hay archivo .env para respaldar
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM Función para restaurar desde sample
|
||||
:restore_env
|
||||
if exist ".env.sample" (
|
||||
copy .env.sample .env >nul
|
||||
echo ✅ Configuración restaurada desde .env.sample
|
||||
echo ⚠️ Recuerda personalizar los valores en .env
|
||||
) else (
|
||||
echo ❌ Archivo .env.sample no encontrado
|
||||
exit /b 1
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM Función principal
|
||||
:main
|
||||
call :print_header
|
||||
|
||||
if "%1"=="" goto help
|
||||
if "%1"=="dev" goto dev
|
||||
if "%1"=="development" goto dev
|
||||
if "%1"=="prod" goto prod
|
||||
if "%1"=="production" goto prod
|
||||
if "%1"=="docker" goto docker
|
||||
if "%1"=="validate" goto validate
|
||||
if "%1"=="check" goto validate
|
||||
if "%1"=="backup" goto backup
|
||||
if "%1"=="restore" goto restore
|
||||
if "%1"=="help" goto help
|
||||
if "%1"=="--help" goto help
|
||||
if "%1"=="-h" goto help
|
||||
|
||||
echo ❌ Comando desconocido: %1
|
||||
echo.
|
||||
goto help
|
||||
|
||||
:dev
|
||||
call :backup_env
|
||||
call :setup_development
|
||||
call :validate_env
|
||||
goto end
|
||||
|
||||
:prod
|
||||
call :backup_env
|
||||
call :setup_production
|
||||
call :validate_env
|
||||
goto end
|
||||
|
||||
:docker
|
||||
call :backup_env
|
||||
call :setup_docker
|
||||
call :validate_env
|
||||
goto end
|
||||
|
||||
:validate
|
||||
call :validate_env
|
||||
goto end
|
||||
|
||||
:backup
|
||||
call :backup_env
|
||||
goto end
|
||||
|
||||
:restore
|
||||
call :backup_env
|
||||
call :restore_env
|
||||
goto end
|
||||
|
||||
:help
|
||||
call :show_help
|
||||
goto end
|
||||
|
||||
:end
|
||||
pause
|
||||
296
scripts/env-setup.sh
Executable file
296
scripts/env-setup.sh
Executable file
@@ -0,0 +1,296 @@
|
||||
#!/bin/bash
|
||||
# ====================================
|
||||
# SCRIPT DE CONFIGURACIÓN DE ENTORNO
|
||||
# Balotario Licencia A-I
|
||||
# ====================================
|
||||
|
||||
set -e # Salir en caso de error
|
||||
|
||||
# Colores para output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Función para imprimir con colores
|
||||
print_info() {
|
||||
echo -e "${ $1${NC}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
print_header() {
|
||||
echo -e "${BLUE}"
|
||||
echo "======================================"
|
||||
echo "🌍 CONFIGURACIÓN DE ENTORNO"
|
||||
echo "Balotario Licencia A-I"
|
||||
echo "======================================"
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# Función para generar SECRET_KEY
|
||||
generate_secret_key() {
|
||||
if command -v python3 &> /dev/null; then
|
||||
python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
elif command -v python &> /dev/null; then
|
||||
python -c "import secrets; print(secrets.token_hex(32))"
|
||||
elif command -v openssl &> /dev/null; then
|
||||
openssl rand -hex 32
|
||||
else
|
||||
# Fallback básico
|
||||
date +%s | sha256sum | base64 | head -c 32
|
||||
fi
|
||||
}
|
||||
|
||||
# Función para configurar desarrollo
|
||||
setup_development() {
|
||||
print_info "Configurando entorno de desarrollo..."
|
||||
|
||||
SECRET_KEY=$(generate_secret_key)
|
||||
|
||||
cat > .env << EOF
|
||||
# ====================================
|
||||
# CONFIGURACIÓN DE DESARROLLO
|
||||
# Generado automáticamente: $(date)
|
||||
# ====================================
|
||||
|
||||
# Configuración de Flask
|
||||
SECRET_KEY=${SECRET_KEY}
|
||||
FLASK_ENV=development
|
||||
FLASK_CONFIG=development
|
||||
FLASK_DEBUG=true
|
||||
|
||||
# Configuración del servidor
|
||||
HOST=127.0.0.1
|
||||
PORT=5000
|
||||
|
||||
# Configuración de Docker
|
||||
DOCKER_CONTAINER=false
|
||||
|
||||
# Configuración de logging
|
||||
LOG_LEVEL=DEBUG
|
||||
AUTO_RELOAD=true
|
||||
SHOW_DEBUG_TOOLBAR=false
|
||||
|
||||
# ====================================
|
||||
# NOTAS:
|
||||
# - Cambia SECRET_KEY antes de ir a producción
|
||||
# - Revisa .env.sample para más opciones
|
||||
# ====================================
|
||||
EOF
|
||||
|
||||
print_success "Configuración de desarrollo creada en .env"
|
||||
}
|
||||
|
||||
# Función para configurar producción
|
||||
setup_production() {
|
||||
print_info "Configurando entorno de producción..."
|
||||
|
||||
SECRET_KEY=$(generate_secret_key)
|
||||
|
||||
cat > .env << EOF
|
||||
# ====================================
|
||||
# CONFIGURACIÓN DE PRODUCCIÓN
|
||||
# Generado automáticamente: $(date)
|
||||
# ====================================
|
||||
|
||||
# Configuración de Flask
|
||||
SECRET_KEY=${SECRET_KEY}
|
||||
FLASK_ENV=production
|
||||
FLASK_CONFIG=production
|
||||
FLASK_DEBUG=false
|
||||
|
||||
# Configuración del servidor
|
||||
HOST=0.0.0.0
|
||||
PORT=5000
|
||||
|
||||
# Configuración de Docker
|
||||
DOCKER_CONTAINER=true
|
||||
|
||||
# Configuración de logging
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# ====================================
|
||||
# IMPORTANTE:
|
||||
# - Guarda SECRET_KEY en lugar seguro
|
||||
# - Revisa todas las configuraciones antes de desplegar
|
||||
# - Considera usar variables de entorno del sistema
|
||||
# ====================================
|
||||
EOF
|
||||
|
||||
print_success "Configuración de producción creada en .env"
|
||||
print_warning "IMPORTANTE: Guarda la SECRET_KEY en un lugar seguro"
|
||||
}
|
||||
|
||||
# Función para configurar Docker
|
||||
setup_docker() {
|
||||
print_info "Configurando entorno para Docker..."
|
||||
|
||||
SECRET_KEY=$(generate_secret_key)
|
||||
|
||||
cat > .env << EOF
|
||||
# ====================================
|
||||
# CONFIGURACIÓN PARA DOCKER
|
||||
# Generado automáticamente: $(date)
|
||||
# ====================================
|
||||
|
||||
# Configuración de Flask
|
||||
SECRET_KEY=${SECRET_KEY}
|
||||
FLASK_ENV=production
|
||||
FLASK_CONFIG=production
|
||||
FLASK_DEBUG=false
|
||||
|
||||
# Configuración del servidor
|
||||
HOST=0.0.0.0
|
||||
PORT=5000
|
||||
|
||||
# Configuración de Docker
|
||||
DOCKER_CONTAINER=true
|
||||
|
||||
# Configuración de logging
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# ====================================
|
||||
# DOCKER NOTES:
|
||||
# - Estas variables pueden ser sobrescritas en docker-compose.yml
|
||||
# - Para desarrollo con Docker, cambia FLASK_ENV=development
|
||||
# ====================================
|
||||
EOF
|
||||
|
||||
print_success "Configuración para Docker creada en .env"
|
||||
}
|
||||
|
||||
# Función para validar configuración
|
||||
validate_env() {
|
||||
print_info "Validando configuración..."
|
||||
|
||||
if [ ! -f ".env" ]; then
|
||||
print_error "Archivo .env no encontrado"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verificar variables esenciales
|
||||
if ! grep -q "SECRET_KEY=" .env; then
|
||||
print_error "SECRET_KEY no encontrada en .env"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! grep -q "FLASK_ENV=" .env; then
|
||||
print_error "FLASK_ENV no encontrada en .env"
|
||||
return 1
|
||||
fi
|
||||
|
||||
print_success "Configuración válida"
|
||||
|
||||
# Mostrar resumen
|
||||
echo ""
|
||||
print_info "Resumen de configuración:"
|
||||
echo "------------------------"
|
||||
grep -E "^(SECRET_KEY|FLASK_ENV|FLASK_DEBUG|HOST|PORT)=" .env | while read line; do
|
||||
key=$(echo $line | cut -d'=' -f1)
|
||||
value=$(echo $line | cut -d'=' -f2)
|
||||
if [ "$key" = "SECRET_KEY" ]; then
|
||||
echo " $key=***OCULTA***"
|
||||
else
|
||||
echo " $key=$value"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Función para mostrar ayuda
|
||||
show_help() {
|
||||
echo "Uso: $0 [COMANDO]"
|
||||
echo ""
|
||||
echo "Comandos disponibles:"
|
||||
echo " dev Configurar para desarrollo local"
|
||||
echo " prod Configurar para producción"
|
||||
echo " docker Configurar para Docker"
|
||||
echo " validate Validar configuración actual"
|
||||
echo " backup Crear backup de .env actual"
|
||||
echo " restore Restaurar desde .env.sample"
|
||||
echo " help Mostrar esta ayuda"
|
||||
echo ""
|
||||
echo "Ejemplos:"
|
||||
echo " $0 dev # Configuración de desarrollo"
|
||||
echo " $0 prod # Configuración de producción"
|
||||
echo " $0 docker # Configuración para Docker"
|
||||
}
|
||||
|
||||
# Función para crear backup
|
||||
backup_env() {
|
||||
if [ -f ".env" ]; then
|
||||
backup_file=".env.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
cp .env "$backup_file"
|
||||
print_success "Backup creado: $backup_file"
|
||||
else
|
||||
print_warning "No hay archivo .env para respaldar"
|
||||
fi
|
||||
}
|
||||
|
||||
# Función para restaurar desde sample
|
||||
restore_env() {
|
||||
if [ -f ".env.sample" ]; then
|
||||
cp .env.sample .env
|
||||
print_success "Configuración restaurada desde .env.sample"
|
||||
print_warning "Recuerda personalizar los valores en .env"
|
||||
else
|
||||
print_error "Archivo .env.sample no encontrado"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Función principal
|
||||
main() {
|
||||
print_header
|
||||
|
||||
case "${1:-help}" in
|
||||
"dev"|"development")
|
||||
backup_env
|
||||
setup_development
|
||||
validate_env
|
||||
;;
|
||||
"prod"|"production")
|
||||
backup_env
|
||||
setup_production
|
||||
validate_env
|
||||
;;
|
||||
"docker")
|
||||
backup_env
|
||||
setup_docker
|
||||
validate_env
|
||||
;;
|
||||
"validate"|"check")
|
||||
validate_env
|
||||
;;
|
||||
"backup")
|
||||
backup_env
|
||||
;;
|
||||
"restore")
|
||||
backup_env
|
||||
restore_env
|
||||
;;
|
||||
"help"|"--help"|"-h")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
print_error "Comando desconocido: $1"
|
||||
echo ""
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Ejecutar función principal
|
||||
main "$@"
|
||||
85
scripts/verify_images.py
Normal file
85
scripts/verify_images.py
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script to verify that all local images are available and working.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
def verify_local_images():
|
||||
"""Verify that all referenced images exist locally."""
|
||||
markdown_file = Path("data/balotario_clase_a_cat_I.md")
|
||||
images_dir = Path("static/images")
|
||||
|
||||
if not markdown_file.exists():
|
||||
print(f"❌ Markdown file not found: {markdown_file}")
|
||||
return False
|
||||
|
||||
if not images_dir.exists():
|
||||
print(f"❌ Images directory not found: {images_dir}")
|
||||
return False
|
||||
|
||||
# Read markdown content
|
||||
with open(markdown_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Find all local image references
|
||||
pattern = r'!\[\]\(/static/images/(img\d+\.jpg)\)'
|
||||
referenced_images = re.findall(pattern, content)
|
||||
|
||||
print(f"🔍 Found {len(referenced_images)} image references in markdown")
|
||||
|
||||
# Check if all referenced images exist
|
||||
missing_images = []
|
||||
existing_images = []
|
||||
|
||||
for img_name in referenced_images:
|
||||
img_path = images_dir / img_name
|
||||
if img_path.exists():
|
||||
existing_images.append(img_name)
|
||||
print(f"✅ {img_name} - {img_path.stat().st_size} bytes")
|
||||
else:
|
||||
missing_images.append(img_name)
|
||||
print(f"❌ {img_name} - NOT FOUND")
|
||||
|
||||
# Check for extra images
|
||||
all_local_images = list(images_dir.glob("*.jpg"))
|
||||
extra_images = []
|
||||
|
||||
for img_path in all_local_images:
|
||||
if img_path.name not in referenced_images:
|
||||
extra_images.append(img_path.name)
|
||||
|
||||
# Summary
|
||||
print(f"\n📊 Verification Summary:")
|
||||
print(f"✅ Images found: {len(existing_images)}")
|
||||
print(f"❌ Images missing: {len(missing_images)}")
|
||||
print(f"📁 Total local images: {len(all_local_images)}")
|
||||
print(f"➕ Extra images: {len(extra_images)}")
|
||||
|
||||
if missing_images:
|
||||
print(f"\n❌ Missing images:")
|
||||
for img in missing_images:
|
||||
print(f" - {img}")
|
||||
|
||||
if extra_images:
|
||||
print(f"\n➕ Extra images (not referenced):")
|
||||
for img in extra_images:
|
||||
print(f" - {img}")
|
||||
|
||||
# Calculate total size
|
||||
total_size = sum(img.stat().st_size for img in all_local_images)
|
||||
print(f"\n💾 Total images size: {total_size / 1024 / 1024:.2f} MB")
|
||||
|
||||
return len(missing_images) == 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("🔍 Verifying local images...")
|
||||
success = verify_local_images()
|
||||
|
||||
if success:
|
||||
print("\n🎉 All images are available locally!")
|
||||
print("💡 Your app can now run completely offline!")
|
||||
else:
|
||||
print("\n⚠️ Some images are missing. Run download_images.py to fix this.")
|
||||
Reference in New Issue
Block a user