diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..b06173b --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,185 @@ +# Guía Rápida de Inicio - WallaMonitor 🚀 + +Esta guía te ayudará a configurar y ejecutar WallaMonitor en menos de 5 minutos. + +## Requisitos Previos + +- Python 3.x instalado +- Un bot de Telegram creado (habla con [@BotFather](https://t.me/botfather)) +- Un canal o grupo de Telegram donde recibir notificaciones + +## Instalación en 4 Pasos + +### 1️⃣ Instalar Dependencias + +```bash +pip3 install -r requirements.txt +``` + +### 2️⃣ Configurar Archivos + +Ejecuta el script de configuración automática: + +```bash +python setup_config.py +``` + +Este script creará automáticamente: +- `config.yaml` desde `config.sample.yaml` +- `workers.json` desde `workers.sample.json` + +**Nota:** Si los archivos ya existen, no se sobrescribirán. + +### 3️⃣ Editar config.yaml + +Abre `config.yaml` y configura tus credenciales: + +```yaml +telegram_token: "TU_TOKEN_AQUI" # Token que te dio BotFather +telegram_channel: "@tu_canal" # Tu canal o grupo de Telegram +``` + +**¿Cómo obtener el token?** +1. Habla con [@BotFather](https://t.me/botfather) en Telegram +2. Envía el comando `/newbot` +3. Sigue las instrucciones y guarda el token que te proporciona + +**¿Cómo configurar el canal?** +- Si es un canal público: `@nombre_canal` +- Si es un grupo: usa el ID numérico (ej: `-1001234567890`) + +### 4️⃣ Configurar Búsquedas (workers.json) + +El archivo `workers.json` contiene ejemplos de búsquedas. Personalízalo según tus necesidades: + +```json +{ + "general": { + "title_exclude": ["palabras", "a", "excluir"], + "description_exclude": ["más", "palabras"] + }, + "items": [ + { + "name": "Mi Búsqueda", + "search_query": "playstation 5", + "platform": "wallapop", + "thread_id": 8, + "title_exclude": ["roto", "piezas"], + "description_exclude": ["no funciona"] + } + ] +} +``` + +**Parámetros importantes:** +- `name`: Nombre descriptivo de la búsqueda +- `search_query`: Término a buscar +- `platform`: `wallapop` (por defecto) o `vinted` +- `thread_id`: ID del hilo de Telegram (opcional) +- `latitude`/`longitude`: Para búsquedas locales (opcional) +- `max_distance`: Distancia máxima en km (opcional) + +## Ejecutar WallaMonitor + +Una vez configurado, simplemente ejecuta: + +```bash +python wallamonitor.py +``` + +El monitor: +- ✅ Verificará la configuración automáticamente +- ✅ Creará archivos faltantes desde los .sample +- ✅ Comenzará a monitorizar tus búsquedas +- ✅ Enviará notificaciones a Telegram cuando encuentre artículos + +## Verificación de Funcionamiento + +Si todo está correcto, verás mensajes como: + +``` +INFO [2025-10-13 10:30:00] Iniciando monitor para: Mi Búsqueda +INFO [2025-10-13 10:30:01] Polling de Telegram iniciado +``` + +Y comenzarás a recibir notificaciones en tu canal de Telegram! + +## Solución de Problemas Comunes + +### Error: "No se encontró config.yaml" +- Ejecuta `python setup_config.py` +- O copia manualmente: `cp config.sample.yaml config.yaml` + +### Error: "Missing mandatory field: items" +- Verifica que `workers.json` tenga la estructura correcta +- Asegúrate de que el campo `items` exista y sea una lista + +### No recibo notificaciones en Telegram +- Verifica que el bot sea administrador del canal +- Comprueba que el token y el canal sean correctos +- Para grupos privados, asegúrate de usar el ID numérico correcto + +### Error de autenticación de Telegram +- Revisa que el token en `config.yaml` sea correcto +- Regenera el token con [@BotFather](https://t.me/botfather) si es necesario + +## Funcionalidades Avanzadas + +### Búsquedas Locales + +```json +{ + "name": "Búsqueda Local", + "search_query": "nintendo switch", + "latitude": 40.4165, + "longitude": -3.70256, + "max_distance": "25" +} +``` + +### Múltiples Plataformas + +```json +{ + "name": "Búsqueda en Vinted", + "platform": "vinted", + "search_query": "zapatillas nike" +} +``` + +### Hilos de Telegram + +Organiza tus notificaciones en diferentes hilos/temas: + +```json +{ + "name": "Consolas Retro", + "search_query": "gameboy", + "thread_id": 10 +} +``` + +## Comandos del Bot de Telegram + +Una vez el bot esté funcionando, puedes usar: + +- `/favs` - Ver tu lista de artículos favoritos +- Botón "⭐ Añadir a favoritos" - Guardar un artículo +- Botón "🗑️ Quitar de favoritos" - Eliminar de favoritos + +## Próximos Pasos + +- 📖 Lee el [README.md](README.md) completo para más opciones +- 🔧 Consulta [ADDING_PLATFORMS.md](ADDING_PLATFORMS.md) para añadir nuevas plataformas +- 🏗️ Revisa [REFACTORING.md](REFACTORING.md) para entender la arquitectura + +## ¿Necesitas Ayuda? + +Si tienes problemas: +1. Verifica los logs en `monitor.log` +2. Revisa que todos los archivos de configuración estén correctos +3. Asegúrate de tener todas las dependencias instaladas + +--- + +**¡Feliz monitoreo! 🛎️** diff --git a/README.md b/README.md index 41e3be0..6936f94 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,28 @@ pip3 install -r requirements.txt ``` - 2. Configura tus credenciales de Telegram en el archivo `config.yaml`: + 2. Configura los archivos de configuración: + + **Opción A - Automática (recomendado):** + ```bash + python setup_config.py + ``` + Este script creará automáticamente `config.yaml` y `workers.json` desde los archivos de muestra si no existen. + + **Opción B - Manual:** + ```bash + cp config.sample.yaml config.yaml + cp workers.sample.json workers.json + ``` + + 3. Edita `config.yaml` con tus credenciales de Telegram: ```yaml telegram_channel: "@Tu_Canal_Telegram" telegram_token: "Tu_Token_De_Telegram" - telegram_chat_id: "Tu_Chat_ID_Telegram" ``` + 4. Personaliza `workers.json` con tus búsquedas deseadas (ver sección Configuración) + ## Configuración 🛠️ Crea un archivo `args.json` con los parámetros de búsqueda. Wallabicher permite definir múltiples búsquedas y personalizar criterios para filtrar exactamente lo que quieres recibir. diff --git a/REFACTORING.md b/REFACTORING.md deleted file mode 100644 index 5a5f84a..0000000 --- a/REFACTORING.md +++ /dev/null @@ -1,207 +0,0 @@ -# Refactorización: Arquitectura Multi-Plataforma - -## Resumen de Cambios - -Se ha refactorizado completamente la arquitectura del proyecto para soportar múltiples plataformas de marketplace (Wallapop, Vinted, Buyee, etc.) mediante un diseño desacoplado y extensible. - -## Cambios Principales - -### 1. Nueva Estructura de Directorios - -``` -├── platforms/ # NUEVO -│ ├── __init__.py -│ ├── base_platform.py # Clase abstracta para plataformas -│ ├── platform_factory.py # Factory para crear plataformas -│ ├── wallapop_platform.py # Implementación de Wallapop -│ ├── vinted_platform_template.py # Template para nuevas plataformas -│ └── README.md # Documentación de plataformas -│ -├── models/ # NUEVO -│ ├── __init__.py -│ └── article.py # Modelo genérico de artículo -│ -└── datalayer/ - └── wallapop_article.py # DEPRECADO (mantener por compatibilidad) -``` - -### 2. Clases Nuevas - -#### `models/article.py` - Modelo Genérico -- **Propósito**: Representa un artículo de cualquier plataforma -- **Cambios respecto a WallapopArticle**: - - Añadido campo `platform` para identificar el origen - - Método `get_images()` devuelve lista directa (no requiere procesamiento) - - Método `get_modified_at()` devuelve string ya formateado - - Igualdad considera plataforma (`id` + `platform`) - -#### `platforms/base_platform.py` - Clase Abstracta -- **Propósito**: Define la interfaz común para todas las plataformas -- **Métodos abstractos**: - - `get_platform_name()`: Retorna identificador de la plataforma - - `create_url()`: Construye URL de búsqueda - - `fetch_articles()`: Obtiene artículos de la plataforma - - `parse_response()`: Parsea respuesta a objetos Article -- **Métodos concretos**: - - `get_request_headers()`: Headers por defecto (puede sobreescribirse) - -#### `platforms/wallapop_platform.py` - Implementación Wallapop -- **Propósito**: Lógica específica de Wallapop -- **Migración desde Worker**: - - `_create_url()` → `create_url()` - - `_request_articles()` → `fetch_articles()` - - `_parse_json_response()` → `parse_response()` -- **Nuevas funcionalidades**: - - Manejo de errores en parseo de artículos individuales - - Logging específico de errores de Wallapop - - Headers específicos de Wallapop (`X-DeviceOS`) - -#### `platforms/platform_factory.py` - Factory Pattern -- **Propósito**: Crear instancias de plataformas dinámicamente -- **Funcionalidades**: - - `create_platform(name, item_monitor)`: Instancia la plataforma - - `get_available_platforms()`: Lista plataformas disponibles - - `register_platform(name, class)`: Registra nuevas plataformas -- **Ventajas**: - - Añadir plataformas sin modificar código existente - - Validación de plataformas soportadas - - Mensajes de error descriptivos - -### 3. Clases Modificadas - -#### `managers/worker.py` - Refactorización Mayor -**Eliminado** (lógica específica de Wallapop): -- `_create_url()` - Movido a `WallapopPlatform.create_url()` -- `_request_articles()` implementación completa - Movido a plataforma -- `_parse_json_response()` - Movido a `WallapopPlatform.parse_response()` -- Imports: `requests`, `WallapopArticle` -- Constantes: `REQUEST_SLEEP_TIME`, `REQUEST_RETRY_TIME`, `USER_AGENT` - -**Añadido** (lógica desacoplada): -- `self._platform`: Instancia de la plataforma configurada -- Inicialización de plataforma mediante `PlatformFactory` -- Manejo de errores de inicialización de plataforma -- Log de plataforma inicializada -- `_request_articles()` ahora delega a `self._platform.fetch_articles()` - -**Mantenido** (lógica común a todas las plataformas): -- `_has_words()`: Búsqueda de palabras en texto -- `_title_has_excluded_words()`: Filtrado de títulos -- `_description_has_excluded_words()`: Filtrado de descripciones -- `_title_has_required_words()`: Palabras requeridas en título -- `_description_has_required_words()`: Palabras requeridas en descripción -- `_title_first_word_is_excluded()`: Filtrado de primera palabra -- `_meets_item_conditions()`: Validación completa de condiciones -- `work()`: Loop principal de trabajo -- `run()`: Manejo de errores y reinicios - -#### `datalayer/item_monitor.py` - Campo de Plataforma -**Añadido**: -- Parámetro `platform` en `__init__()` -- Campo `self._platform` -- Método `get_platform()` -- Default `'wallapop'` en `load_from_json()` para compatibilidad hacia atrás - -### 4. Archivos de Configuración - -#### `workers.json` - Campo Opcional de Plataforma -**Añadido**: -- Campo `"platform": "wallapop"` en primer item como ejemplo -- Otros items usan el default (wallapop) por compatibilidad - -**Ejemplo**: -```json -{ - "name": "Playstation 1", - "platform": "wallapop", - "search_query": "playstation", - ... -} -``` - -### 5. Documentación - -#### `platforms/README.md` - Guía Completa -- Introducción a la arquitectura de plataformas -- Cómo añadir una nueva plataforma (paso a paso) -- Parámetros disponibles en ItemMonitor -- Estructura del modelo Article -- Lógica común del Worker vs lógica de plataforma - -#### `platforms/vinted_platform_template.py` - Plantilla -- Implementación esqueleto para Vinted -- TODOs marcados claramente -- Comentarios explicativos -- Estructura JSON de ejemplo -- Pasos de activación - -#### `README.md` - Actualización Principal -- Nueva sección "Arquitectura Multi-Plataforma" -- Nueva sección "Añadir Nuevas Plataformas" -- Actualización de descripción del proyecto -- Tabla de parámetros con campo `platform` -- Diagrama de estructura del proyecto -- Lista de plataformas soportadas - -## Ventajas de la Nueva Arquitectura - -### ✅ Desacoplamiento -- Lógica de plataforma separada de lógica de filtrado -- Cada componente tiene una responsabilidad única -- Fácil de mantener y testear - -### ✅ Extensibilidad -- Añadir plataformas sin tocar código existente -- Factory pattern permite registro dinámico -- Plantillas y documentación para nuevas plataformas - -### ✅ Reutilización -- Filtros comunes para todas las plataformas -- Modelo Article unificado -- Worker genérico - -### ✅ Mantenibilidad -- Código más limpio y organizado -- Responsabilidades claras -- Fácil de entender y modificar - -## Compatibilidad Hacia Atrás - -✅ **100% Compatible**: El código existente funciona sin cambios -- Items sin campo `platform` usan "wallapop" por defecto -- `WallapopArticle` aún existe (aunque ya no se usa) -- Mismos filtros y funcionalidad - -## Próximos Pasos - -Para añadir nuevas plataformas: - -1. **Vinted**: Completar el template existente -2. **Buyee**: Crear nueva implementación -3. **Amazon**: Posible integración futura -4. **eBay**: Posible integración futura - -## Migración - -No se requiere migración. El sistema funciona con configuraciones existentes. - -Para aprovechar las nuevas funcionalidades: -1. Añade `"platform": "wallapop"` a tus items en `workers.json` (opcional) -2. Implementa nuevas plataformas según `platforms/README.md` - -## Testing - -Recomendaciones para testing: -1. Verificar que Wallapop sigue funcionando igual -2. Probar con configuraciones sin campo `platform` -3. Validar que los filtros funcionan con el nuevo modelo Article -4. Probar manejo de errores en inicialización de plataformas - -## Archivos a Mantener (Deprecados) - -- `datalayer/wallapop_article.py`: Mantener por si hay dependencias externas - -## Cambios en Dependencias - -Ninguno. Las mismas dependencias funcionan con la nueva arquitectura. - diff --git a/SUMMARY.md b/SUMMARY.md deleted file mode 100644 index 88e81a2..0000000 --- a/SUMMARY.md +++ /dev/null @@ -1,331 +0,0 @@ -# ✅ Resumen de la Refactorización Multi-Plataforma - -## 🎯 Objetivo Completado - -Se ha desacoplado exitosamente la lógica específica de Wallapop del Worker, implementando una arquitectura extensible que permite añadir múltiples plataformas (Vinted, Buyee, etc.) sin modificar el código existente. - ---- - -## 📦 Archivos Creados - -### Nuevos Directorios -``` -platforms/ # Implementaciones de plataformas -models/ # Modelos de datos genéricos -``` - -### Nuevos Archivos de Código -``` -✅ models/__init__.py -✅ models/article.py # Modelo genérico de artículo -✅ platforms/__init__.py -✅ platforms/base_platform.py # Clase abstracta base -✅ platforms/platform_factory.py # Factory para crear plataformas -✅ platforms/wallapop_platform.py # Implementación de Wallapop -✅ platforms/vinted_platform_template.py # Plantilla para Vinted -``` - -### Nuevos Archivos de Documentación -``` -✅ REFACTORING.md # Resumen técnico completo -✅ ADDING_PLATFORMS.md # Guía para Vinted y Buyee -✅ platforms/README.md # Documentación de plataformas -✅ SUMMARY.md # Este archivo -``` - ---- - -## 🔄 Archivos Modificados - -### Código -``` -✅ managers/worker.py # Refactorizado para usar plataformas -✅ datalayer/item_monitor.py # Añadido campo 'platform' -✅ workers.json # Ejemplo con campo 'platform' -``` - -### Documentación -``` -✅ README.md # Actualizado con nueva arquitectura -``` - ---- - -## 🏗️ Arquitectura Implementada - -### Patrón de Diseño: Strategy + Factory - -``` -┌─────────────────────────────────────────────────────┐ -│ Worker │ -│ (Lógica común: filtros, validaciones) │ -└────────────────┬────────────────────────────────────┘ - │ - │ usa - ▼ -┌─────────────────────────────────────────────────────┐ -│ PlatformFactory │ -│ (Crea instancias de plataformas) │ -└────────────────┬────────────────────────────────────┘ - │ - │ crea - ▼ -┌─────────────────────────────────────────────────────┐ -│ BasePlatform │ -│ (Interfaz abstracta) │ -└────────────────┬────────────────────────────────────┘ - │ - ┌───────┴────────┬─────────────┬──────────┐ - ▼ ▼ ▼ ▼ - ┌────────────┐ ┌──────────┐ ┌─────────┐ ┌──────┐ - │ Wallapop │ │ Vinted │ │ Buyee │ │ ... │ - │ Platform │ │ Platform │ │Platform │ │ │ - └────────────┘ └──────────┘ └─────────┘ └──────┘ - │ │ │ │ - └────────────────┴─────────────┴──────────┘ - │ - ▼ - ┌────────────┐ - │ Article │ - │ (Modelo) │ - └────────────┘ -``` - ---- - -## 🎨 Separación de Responsabilidades - -### ✅ Lógica COMÚN (Worker) -Aplicada a todas las plataformas: -- ✓ Filtrado por palabras excluidas en título -- ✓ Filtrado por palabras excluidas en descripción -- ✓ Filtrado por palabras requeridas -- ✓ Filtrado por primera palabra del título -- ✓ Deduplicación de artículos -- ✓ Gestión de cola de notificaciones -- ✓ Manejo de errores y reintentos -- ✓ Logging y estadísticas - -### 🔧 Lógica ESPECÍFICA (Plataformas) -Cada plataforma implementa: -- 🔧 Construcción de URL de búsqueda -- 🔧 Headers HTTP específicos -- 🔧 Peticiones a la API/sitio web -- 🔧 Parseo de respuestas JSON/HTML -- 🔧 Conversión a modelo Article genérico - ---- - -## 📊 Comparativa: Antes vs Después - -### Antes (Monolítico) -``` -Worker -├── Lógica de Wallapop (URL, API, parseo) -├── Lógica de filtrado -└── Gestión de artículos - -❌ Difícil añadir nuevas plataformas -❌ Código mezclado -❌ No reutilizable -``` - -### Después (Desacoplado) -``` -Worker -└── Lógica de filtrado (común) - -Plataformas (separadas) -├── WallapopPlatform -├── VintedPlatform (plantilla) -└── BuyeePlatform (por implementar) - -✅ Fácil añadir plataformas -✅ Código organizado -✅ Altamente reutilizable -``` - ---- - -## 🚀 Cómo Usar - -### 1. Configuración Básica (Wallapop - Compatible) -Sin cambios necesarios, funciona con tu `workers.json` actual: - -```json -{ - "name": "Gameboy", - "search_query": "gameboy", - "min_price": 10, - "max_price": 100 -} -``` - -### 2. Configuración Explícita (Recomendado) -Especifica la plataforma: - -```json -{ - "name": "Gameboy en Wallapop", - "platform": "wallapop", - "search_query": "gameboy", - "min_price": 10, - "max_price": 100 -} -``` - -### 3. Añadir Nueva Plataforma (Vinted) -Una vez implementada: - -```json -{ - "name": "Gameboy en Vinted", - "platform": "vinted", - "search_query": "gameboy", - "min_price": 10, - "max_price": 100, - "thread_id": 12 -} -``` - ---- - -## 📝 Próximos Pasos para Vinted y Buyee - -### Vinted (Más Fácil) -1. Usa la plantilla en `platforms/vinted_platform_template.py` -2. Completa los métodos con la API de Vinted -3. Registra en `platform_factory.py` -4. Prueba con búsquedas reales - -**Documentación**: Ver `ADDING_PLATFORMS.md` para código completo - -### Buyee (Más Complejo) -1. Decide entre API de Yahoo o web scraping -2. Implementa siguiendo el ejemplo en `ADDING_PLATFORMS.md` -3. Instala BeautifulSoup si usas scraping: `pip install beautifulsoup4` -4. Registra en `platform_factory.py` - -**Documentación**: Ver `ADDING_PLATFORMS.md` para código completo - ---- - -## ✅ Testing Realizado - -``` -✅ Imports funcionan correctamente -✅ PlatformFactory crea plataformas -✅ ItemMonitor soporta campo 'platform' -✅ Modelo Article funciona correctamente -✅ Validación de plataformas no soportadas -``` - -**Resultado**: 5/5 tests pasados ✓ - ---- - -## 📚 Documentación Disponible - -| Archivo | Propósito | -|---------|-----------| -| `README.md` | Documentación principal del proyecto | -| `REFACTORING.md` | Detalles técnicos de la refactorización | -| `ADDING_PLATFORMS.md` | Guía completa para Vinted y Buyee | -| `platforms/README.md` | Cómo añadir cualquier plataforma | -| `SUMMARY.md` | Este resumen ejecutivo | - ---- - -## 🔄 Compatibilidad - -### ✅ 100% Compatible con Código Existente -- Workers sin campo `platform` usan "wallapop" por defecto -- Misma funcionalidad de filtrado -- Mismos resultados -- No requiere cambios en configuración - -### 🆕 Nuevas Capacidades -- Soporte multi-plataforma -- Arquitectura extensible -- Fácil mantenimiento -- Código más limpio - ---- - -## 🎓 Conceptos Implementados - -- ✅ **Strategy Pattern**: Diferentes estrategias de búsqueda por plataforma -- ✅ **Factory Pattern**: Creación dinámica de plataformas -- ✅ **Dependency Injection**: Worker recibe plataforma -- ✅ **Open/Closed Principle**: Abierto a extensión, cerrado a modificación -- ✅ **Single Responsibility**: Cada clase tiene una responsabilidad -- ✅ **DRY**: Lógica común no se repite - ---- - -## 📈 Beneficios Conseguidos - -### Para el Desarrollo -- ✅ Código más limpio y organizado -- ✅ Fácil de mantener y depurar -- ✅ Testing más simple -- ✅ Documentación completa - -### Para Añadir Plataformas -- ✅ Solo 3 pasos para añadir una plataforma -- ✅ Plantillas y ejemplos disponibles -- ✅ No tocar código existente -- ✅ Factory maneja instanciación - -### Para el Usuario -- ✅ Más plataformas disponibles -- ✅ Mismos filtros en todas -- ✅ Configuración simple -- ✅ Sin cambios en workers.json existente - ---- - -## 🎉 Resultado Final - -**Sistema completamente funcional y probado** que: - -1. ✅ Mantiene toda la funcionalidad de Wallapop -2. ✅ Permite añadir Vinted fácilmente -3. ✅ Permite añadir Buyee con guía completa -4. ✅ Es 100% compatible con configuración existente -5. ✅ Tiene arquitectura profesional y escalable -6. ✅ Incluye documentación completa -7. ✅ Ha pasado todos los tests - ---- - -## 💡 Empezar a Usar - -### Opción 1: Seguir como Antes -```bash -# No hagas nada, ya funciona con tu workers.json actual -python3 wallamonitor.py -``` - -### Opción 2: Añadir Vinted -1. Lee `ADDING_PLATFORMS.md` -2. Copia el código de Vinted -3. Registra la plataforma -4. Añade items con `"platform": "vinted"` en workers.json -5. ¡Listo! - -### Opción 3: Añadir Buyee -1. Lee `ADDING_PLATFORMS.md` -2. Decide API vs Scraping -3. Implementa según el ejemplo -4. Instala dependencias si es necesario -5. Registra y usa - ---- - -**¿Preguntas?** Consulta la documentación en los archivos `.md` creados. - -**¿Problemas?** Revisa `REFACTORING.md` para detalles técnicos. - -**¿Añadir plataforma?** Sigue `ADDING_PLATFORMS.md` o `platforms/README.md`. - diff --git a/setup_config.py b/setup_config.py new file mode 100755 index 0000000..5c6895f --- /dev/null +++ b/setup_config.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +""" +Script de inicialización de configuración para WallaMonitor. + +Este script copia los archivos de configuración de muestra (.sample) +a sus ubicaciones finales si estos no existen. + +Uso: + python setup_config.py +""" + +import os +import shutil +import sys + +def setup_configuration(): + """ + Inicializa los archivos de configuración necesarios. + """ + base_dir = os.path.dirname(os.path.abspath(__file__)) + + config_files = [ + { + 'name': 'config.yaml', + 'sample': 'config.sample.yaml', + 'description': 'Configuración de Telegram (token y canal)' + }, + { + 'name': 'workers.json', + 'sample': 'workers.sample.json', + 'description': 'Configuración de búsquedas y monitores' + } + ] + + print("="*60) + print(" WallaMonitor - Configuración Inicial") + print("="*60) + print() + + files_created = False + files_exist = [] + + for config in config_files: + config_path = os.path.join(base_dir, config['name']) + sample_path = os.path.join(base_dir, config['sample']) + + if os.path.exists(config_path): + files_exist.append(config['name']) + print(f"✓ '{config['name']}' ya existe (no se sobrescribirá)") + elif os.path.exists(sample_path): + try: + shutil.copy2(sample_path, config_path) + files_created = True + print(f"✓ '{config['name']}' creado desde '{config['sample']}'") + print(f" → {config['description']}") + except Exception as e: + print(f"✗ Error al crear '{config['name']}': {e}") + return False + else: + print(f"✗ ERROR: No se encontró el archivo de muestra '{config['sample']}'") + return False + + print() + print("="*60) + + if files_created: + print("\n⚠️ IMPORTANTE: Edita los archivos de configuración antes de ejecutar:") + print() + print(" 1. config.yaml:") + print(" - Añade tu token de Telegram Bot") + print(" - Configura el canal/grupo de destino") + print() + print(" 2. workers.json:") + print(" - Ajusta las búsquedas según tus necesidades") + print(" - Configura los thread_id para tus hilos de Telegram") + print() + print(" Luego ejecuta: python wallamonitor.py") + elif files_exist: + print("\n✓ Todos los archivos de configuración ya existen.") + print(" El sistema está listo para usar.") + + print("\n" + "="*60) + return True + +if __name__ == "__main__": + success = setup_configuration() + sys.exit(0 if success else 1) + diff --git a/wallamonitor.py b/wallamonitor.py index 1f83411..f183c79 100644 --- a/wallamonitor.py +++ b/wallamonitor.py @@ -2,12 +2,41 @@ import json import logging from logging.handlers import RotatingFileHandler from concurrent.futures import ThreadPoolExecutor +import os +import shutil from datalayer.item_monitor import ItemMonitor from datalayer.general_monitor import GeneralMonitor from managers.worker import Worker from managers.queue_manager import QueueManager +def initialize_config_files(): + """ + Inicializa los archivos de configuración si no existen, + copiando los archivos .sample correspondientes. + """ + base_dir = os.path.dirname(os.path.abspath(__file__)) + + config_files = [ + ('config.yaml', 'config.sample.yaml'), + ('workers.json', 'workers.sample.json') + ] + + for config_file, sample_file in config_files: + config_path = os.path.join(base_dir, config_file) + sample_path = os.path.join(base_dir, sample_file) + + if not os.path.exists(config_path): + if os.path.exists(sample_path): + shutil.copy2(sample_path, config_path) + print(f"✓ Archivo '{config_file}' creado desde '{sample_file}'") + print(f" Por favor, edita '{config_file}' con tu configuración antes de continuar.") + else: + raise FileNotFoundError( + f"No se encontró ni '{config_file}' ni '{sample_file}'. " + f"Por favor, crea uno de estos archivos." + ) + def configure_logger(): logging.getLogger("httpx").setLevel(logging.WARNING) @@ -36,6 +65,7 @@ def parse_items_to_monitor(): return items, general_args if __name__ == "__main__": + initialize_config_files() configure_logger() items, general_args = parse_items_to_monitor()