# Reciclaje de Contenido Sistema para republica contenido exitoso y maximizar su alcance. ## Descripción El reciclaje de contenido permite: - Identificar posts con alto engagement - Republicarlos con modificaciones opcionales - Trackear rendimiento de versiones recicladas - Automatizar el proceso de reciclaje ## Modelo de Datos ### RecycledPost ```python RecycledPost: id: int original_post_id: int (FK -> posts) new_post_id: int (FK -> posts) recycle_number: int # 1, 2, 3... (veces reciclado) modifications: JSON # {"content_changed": true, "hashtags_updated": true, "image_changed": false} modification_notes: str original_engagement_rate: float new_engagement_rate: float status: str # pending, published, cancelled reason: str # high_performer, evergreen, seasonal, manual recycled_at: datetime scheduled_for: datetime ``` ### Campos en Post ```python # Campos añadidos al modelo Post is_recyclable: bool # Si puede ser reciclado (default True) recycled_from_id: int (FK -> posts) # Post original si es reciclado recycle_count: int # Veces que este post ha sido reciclado ``` ## Configuración ```python # En recycling_service.py MIN_DAYS_SINCE_PUBLISH = 30 # No reciclar posts recientes MIN_ENGAGEMENT_RATE = 2.0 # Mínimo 2% engagement MAX_RECYCLE_COUNT = 3 # Máximo 3 veces por post ``` ## API Endpoints ### GET /api/recycling/candidates Obtiene posts candidatos para reciclar. **Parámetros:** - `platform` (str): Filtrar por plataforma - `content_type` (str): Filtrar por tipo de contenido - `min_engagement_rate` (float, default=2.0): Engagement mínimo - `min_days` (int, default=30): Días desde publicación - `limit` (int, default=20): Máximo candidatos **Respuesta:** ```json { "candidates": [ { "id": 123, "content": "Tip: Usa IA para automatizar...", "full_content": "...", "content_type": "tip_tech", "platforms": ["x"], "published_at": "2024-12-01T10:00:00", "days_since_publish": 58, "engagement_rate": 4.5, "recycle_count": 0, "score": 3.8, "metrics": {"likes": 150, "comments": 30} } ], "count": 10, "filters": { "min_engagement_rate": 2.0, "min_days": 30 } } ``` ### POST /api/recycling/{post_id} Recicla un post específico. **Body (opcional):** ```json { "content": "Versión actualizada del contenido...", "hashtags": ["#nuevo", "#hashtag"], "image_url": "https://...", "scheduled_for": "2025-02-01T10:00:00", "platforms": ["x", "threads"], "reason": "high_performer" } ``` **Respuesta:** ```json { "message": "Post recycled successfully", "success": true, "new_post_id": 456, "recycle_record_id": 1, "scheduled_for": "2025-02-01T10:00:00", "platforms": ["x", "threads"] } ``` ### POST /api/recycling/auto Reciclaje automático de mejores posts. **Parámetros:** - `platform` (str, opcional): Plataforma específica - `count` (int, default=1, max=5): Cantidad a reciclar - `min_engagement_rate` (float, default=2.0) **Respuesta:** ```json { "success": true, "recycled": 2, "posts": [ { "original_id": 123, "new_post_id": 456, "engagement_rate": 4.5 } ] } ``` ### GET /api/recycling/history Obtiene historial de reciclaje. **Parámetros:** - `original_post_id` (int, opcional): Filtrar por post original - `limit` (int, default=50) ### POST /api/recycling/{post_id}/disable Marca un post como no reciclable. ## Sistema de Puntuación Los candidatos se puntúan con la fórmula: ```python score = engagement_rate * recency_factor * recycled_penalty donde: recency_factor = min(days_since_publish / 90, 1.0) recycled_penalty = 1 - (recycle_count * 0.2) ``` ### Ejemplo | Post | Engagement | Días | Reciclajes | Score | |------|------------|------|------------|-------| | A | 4.0% | 60 | 0 | 4.0 × 0.67 × 1.0 = 2.68 | | B | 5.0% | 90 | 1 | 5.0 × 1.0 × 0.8 = 4.00 | | C | 3.0% | 45 | 0 | 3.0 × 0.5 × 1.0 = 1.50 | Post B tiene el score más alto. ## Tareas Programadas ### auto_recycle_content - **Frecuencia:** Diario a las 2:00 AM - **Función:** - Busca 1 post por plataforma con engagement > 3% - Programa reciclaje automático - **Plataformas:** x, threads ## Flujo de Reciclaje ``` 1. Identificar Candidatos - Posts con > 30 días de antigüedad - Engagement rate > 2% - recycle_count < 3 - is_recyclable = true ↓ 2. Seleccionar por Score - Ordenar por score descendente ↓ 3. Crear Post Reciclado - Clonar contenido (o modificar) - Establecer recycled_from_id - Programar publicación ↓ 4. Registrar en RecycledPost - Guardar relación - Incrementar recycle_count del original ↓ 5. Publicar y Trackear - Comparar new_engagement_rate vs original ``` ## Razones de Reciclaje | Razón | Descripción | |-------|-------------| | `high_performer` | Post con engagement alto | | `evergreen` | Contenido atemporal relevante | | `seasonal` | Contenido de temporada que regresa | | `manual` | Reciclado manualmente | ## Ejemplo de Uso ```python from app.services.recycling_service import recycling_service # Buscar candidatos candidates = await recycling_service.find_recyclable_posts( platform="x", min_engagement_rate=3.0, limit=10 ) for candidate in candidates: print(f"Post {candidate['id']}: {candidate['engagement_rate']}% - Score {candidate['score']}") # Reciclar manualmente result = await recycling_service.recycle_post( post_id=123, modifications={"content": "Versión actualizada..."}, reason="evergreen" ) # Reciclaje automático result = await recycling_service.auto_recycle( platform="x", count=2 ) ``` ## Mejores Prácticas 1. **Esperar suficiente tiempo:** Mínimo 30 días entre reciclajes 2. **Modificar ligeramente:** Actualiza hashtags o intro 3. **No abusar:** Máximo 3 reciclajes por post 4. **Monitorear:** Compara rendimiento nuevo vs original 5. **Contenido evergreen:** Prioriza contenido atemporal ## Tipos de Contenido Ideales para Reciclar | Tipo | Ideal | Razón | |------|-------|-------| | Tips técnicos | ✅ | Siempre relevantes | | Tutoriales | ✅ | Valor educativo permanente | | Productos | ⚠️ | Si stock disponible | | Promociones | ❌ | Fechas específicas | | Efemérides | ❌ | Fechas específicas | | Noticias | ❌ | Se vuelven obsoletas |