docs: Add comprehensive documentation for all new features
- FEATURES_OVERVIEW.md: Complete summary of all system features - ANALYTICS.md: Analytics and reporting system documentation - ODOO_INTEGRATION.md: Odoo ERP integration guide - AB_TESTING.md: A/B testing system documentation - CONTENT_RECYCLING.md: Content recycling system docs - THREAD_SERIES.md: Thread series and scheduled posts - IMAGE_TEMPLATES.md: Visual template system documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
267
docs/CONTENT_RECYCLING.md
Normal file
267
docs/CONTENT_RECYCLING.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user