Implementación inicial del sistema de automatización de redes sociales

- Estructura completa del proyecto con FastAPI
- Modelos de base de datos (productos, servicios, posts, calendario, interacciones)
- Publishers para X, Threads, Instagram, Facebook
- Generador de contenido con DeepSeek API
- Worker de Celery con tareas programadas
- Dashboard básico con templates HTML
- Docker Compose para despliegue
- Documentación completa

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-28 01:11:44 +00:00
commit 049d2133f9
53 changed files with 5876 additions and 0 deletions

87
app/models/interaction.py Normal file
View File

@@ -0,0 +1,87 @@
"""
Modelo de Interaction - Interacciones en redes sociales.
"""
from datetime import datetime
from sqlalchemy import Column, Integer, String, Text, Boolean, DateTime, ForeignKey
from app.core.database import Base
class Interaction(Base):
"""Modelo para interacciones (comentarios, DMs, menciones)."""
__tablename__ = "interactions"
id = Column(Integer, primary_key=True, index=True)
# Plataforma
platform = Column(String(50), nullable=False, index=True)
# Valores: x, threads, instagram, facebook
# Tipo de interacción
interaction_type = Column(String(50), nullable=False, index=True)
# Tipos: comment, reply, dm, mention, like, repost, quote
# Post relacionado (si aplica)
post_id = Column(Integer, ForeignKey("posts.id"), nullable=True)
# ID externo en la plataforma
external_id = Column(String(100), nullable=False, unique=True)
external_post_id = Column(String(100), nullable=True) # ID del post en la plataforma
# Autor de la interacción
author_username = Column(String(100), nullable=False)
author_name = Column(String(255), nullable=True)
author_profile_url = Column(String(500), nullable=True)
author_avatar_url = Column(String(500), nullable=True)
# Contenido
content = Column(Text, nullable=True)
# Respuesta
responded = Column(Boolean, default=False, index=True)
response_content = Column(Text, nullable=True)
responded_at = Column(DateTime, nullable=True)
response_external_id = Column(String(100), nullable=True)
# Clasificación
is_lead = Column(Boolean, default=False) # Potencial cliente
sentiment = Column(String(50), nullable=True) # positive, negative, neutral
priority = Column(Integer, default=0) # 0=normal, 1=importante, 2=urgente
# Estado
is_read = Column(Boolean, default=False)
is_archived = Column(Boolean, default=False)
# Timestamps
interaction_at = Column(DateTime, nullable=False) # Cuándo ocurrió en la plataforma
created_at = Column(DateTime, default=datetime.utcnow) # Cuándo se guardó aquí
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f"<Interaction {self.platform} - {self.interaction_type} - {self.author_username}>"
def to_dict(self):
"""Convertir a diccionario."""
return {
"id": self.id,
"platform": self.platform,
"interaction_type": self.interaction_type,
"post_id": self.post_id,
"external_id": self.external_id,
"author_username": self.author_username,
"author_name": self.author_name,
"author_profile_url": self.author_profile_url,
"author_avatar_url": self.author_avatar_url,
"content": self.content,
"responded": self.responded,
"response_content": self.response_content,
"responded_at": self.responded_at.isoformat() if self.responded_at else None,
"is_lead": self.is_lead,
"sentiment": self.sentiment,
"priority": self.priority,
"is_read": self.is_read,
"interaction_at": self.interaction_at.isoformat() if self.interaction_at else None,
"created_at": self.created_at.isoformat() if self.created_at else None
}