- 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>
88 lines
3.3 KiB
Python
88 lines
3.3 KiB
Python
"""
|
|
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
|
|
}
|