240 lines
8.7 KiB
Python
240 lines
8.7 KiB
Python
import datetime
|
|
from sqlalchemy import create_engine, Column, Integer, String, Boolean, DateTime, Text
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
Base = declarative_base()
|
|
|
|
class Media(Base):
|
|
__tablename__ = 'media'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
file_path = Column(String, unique=True, nullable=False)
|
|
file_type = Column(String) # 'image' or 'audio'
|
|
artist_id = Column(String)
|
|
is_used = Column(Boolean, default=False)
|
|
description = Column(Text)
|
|
source_url = Column(String)
|
|
thumbnail_path = Column(String) # NUOVO
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
last_used_at = Column(DateTime)
|
|
|
|
class Draft(Base):
|
|
__tablename__ = 'drafts'
|
|
id = Column(Integer, primary_key=True)
|
|
artist_id = Column(String)
|
|
title = Column(String)
|
|
caption = Column(Text)
|
|
hashtags = Column(Text)
|
|
image_path = Column(String)
|
|
image_paths = Column(Text) # JSON list of local paths
|
|
image_url = Column(String) # NUOVA COLONNA PER ANTEPRIMA DIRETTA
|
|
video_url = Column(String)
|
|
video_path = Column(String) # NUOVO
|
|
audio_analysis = Column(Text)
|
|
focus_points = Column(Text) # NUOVO: Coordinate JSON per la regia AI
|
|
status = Column(String, default='pending') # pending, approved, published
|
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
|
|
|
class Database:
|
|
def __init__(self, db_url="sqlite:///data/redazione.db"):
|
|
self.engine = create_engine(db_url)
|
|
Base.metadata.create_all(self.engine)
|
|
self.Session = sessionmaker(bind=self.engine)
|
|
|
|
def add_media(self, file_path, file_type, artist_id, description=None, source_url=None, thumbnail_path=None):
|
|
session = self.Session()
|
|
try:
|
|
media = session.query(Media).filter_by(file_path=file_path).first()
|
|
if not media:
|
|
media = Media(
|
|
file_path=file_path,
|
|
file_type=file_type,
|
|
artist_id=artist_id,
|
|
description=description,
|
|
source_url=source_url,
|
|
thumbnail_path=thumbnail_path
|
|
)
|
|
session.add(media)
|
|
session.commit()
|
|
elif thumbnail_path and not media.thumbnail_path:
|
|
media.thumbnail_path = thumbnail_path
|
|
session.commit()
|
|
return media
|
|
finally:
|
|
session.close()
|
|
|
|
def get_unused_image(self, artist_id):
|
|
from sqlalchemy.sql.expression import func
|
|
session = self.Session()
|
|
try:
|
|
return session.query(Media).filter_by(
|
|
artist_id=artist_id,
|
|
file_type='image',
|
|
is_used=False
|
|
).order_by(func.random()).first()
|
|
finally:
|
|
session.close()
|
|
|
|
def get_media_by_artist(self, artist_id, file_type):
|
|
session = self.Session()
|
|
try:
|
|
return session.query(Media).filter_by(
|
|
artist_id=artist_id,
|
|
file_type=file_type
|
|
).first()
|
|
finally:
|
|
session.close()
|
|
|
|
def get_audio_for_artist(self, artist_id):
|
|
return self.get_media_by_artist(artist_id, 'audio')
|
|
|
|
def mark_as_used(self, media_id):
|
|
session = self.Session()
|
|
try:
|
|
media = session.query(Media).get(media_id)
|
|
if media:
|
|
media.is_used = True
|
|
media.last_used_at = datetime.datetime.utcnow()
|
|
session.commit()
|
|
finally:
|
|
session.close()
|
|
|
|
def get_audio_for_artist(self, artist_id):
|
|
# We assume one main audio track per session or the latest added
|
|
session = self.Session()
|
|
try:
|
|
return session.query(Media).filter_by(
|
|
artist_id=artist_id,
|
|
file_type='audio'
|
|
).order_by(Media.created_at.desc()).first()
|
|
finally:
|
|
session.close()
|
|
|
|
def save_draft(self, artist_id, title, caption, hashtags, image_path, audio_analysis, image_url=None, video_url=None, image_paths=None, video_path=None, focus_points=None):
|
|
session = self.Session()
|
|
try:
|
|
draft = Draft(
|
|
artist_id=artist_id,
|
|
title=title,
|
|
caption=caption,
|
|
hashtags=hashtags,
|
|
image_path=image_path,
|
|
image_paths=image_paths,
|
|
image_url=image_url,
|
|
video_url=video_url,
|
|
video_path=video_path,
|
|
audio_analysis=audio_analysis,
|
|
focus_points=focus_points # SALVATAGGIO
|
|
)
|
|
session.add(draft)
|
|
session.commit()
|
|
return draft.id
|
|
finally:
|
|
session.close()
|
|
|
|
def get_recent_media(self, artist_id, limit=10):
|
|
session = self.Session()
|
|
try:
|
|
return session.query(Media).filter(
|
|
Media.artist_id == artist_id,
|
|
Media.file_type.in_(['image', 'video'])
|
|
).order_by(Media.created_at.desc()).limit(limit).all()
|
|
finally:
|
|
session.close()
|
|
|
|
def get_mixed_assets(self, artist_id, total=12):
|
|
from sqlalchemy.sql.expression import func
|
|
session = self.Session()
|
|
try:
|
|
# 1. Seleziona una copertina (preferibilmente immagine mai usata)
|
|
cover = session.query(Media).filter_by(
|
|
artist_id=artist_id,
|
|
file_type='image',
|
|
is_used=False
|
|
).order_by(func.random()).first()
|
|
|
|
if not cover:
|
|
cover = session.query(Media).filter_by(
|
|
artist_id=artist_id,
|
|
file_type='image'
|
|
).order_by(func.random()).first()
|
|
|
|
if not cover:
|
|
# Se proprio non ci sono immagini, prendi un video come cover
|
|
cover = session.query(Media).filter_by(
|
|
artist_id=artist_id,
|
|
file_type='video'
|
|
).order_by(func.random()).first()
|
|
|
|
if not cover:
|
|
return []
|
|
|
|
# 2. Seleziona un mix di altre immagini e video
|
|
others = session.query(Media).filter(
|
|
Media.artist_id == artist_id,
|
|
Media.file_type.in_(['image', 'video']),
|
|
Media.id != cover.id
|
|
).order_by(func.random()).limit(total - 1).all()
|
|
|
|
return [cover] + others
|
|
finally:
|
|
session.close()
|
|
|
|
def get_pending_drafts(self, artist_id=None):
|
|
session = self.Session()
|
|
try:
|
|
query = session.query(Draft).filter_by(status='pending')
|
|
if artist_id:
|
|
query = query.filter_by(artist_id=artist_id)
|
|
return query.all()
|
|
finally:
|
|
session.close()
|
|
def get_media_by_path(self, file_path):
|
|
session = self.Session()
|
|
try:
|
|
return session.query(Media).filter_by(file_path=file_path).first()
|
|
finally:
|
|
session.close()
|
|
|
|
def delete_draft(self, draft_id):
|
|
session = self.Session()
|
|
try:
|
|
draft = session.query(Draft).filter_by(id=draft_id).first()
|
|
if draft:
|
|
session.delete(draft)
|
|
session.commit()
|
|
finally:
|
|
session.close()
|
|
|
|
def update_draft(self, draft_id, title=None, caption=None, hashtags=None, image_path=None, status=None, audio_analysis=None, video_url=None, video_path=None, image_paths=None, focus_points=None):
|
|
session = self.Session()
|
|
try:
|
|
draft = session.query(Draft).get(draft_id)
|
|
if draft:
|
|
if title is not None: draft.title = title
|
|
if caption is not None: draft.caption = caption
|
|
if hashtags is not None: draft.hashtags = hashtags
|
|
if image_path is not None: draft.image_path = image_path
|
|
if status is not None: draft.status = status
|
|
if audio_analysis is not None: draft.audio_analysis = audio_analysis
|
|
if video_url is not None: draft.video_url = video_url
|
|
if video_path is not None: draft.video_path = video_path
|
|
if image_paths is not None: draft.image_paths = image_paths
|
|
if focus_points is not None: draft.focus_points = focus_points # AGGIORNAMENTO
|
|
session.commit()
|
|
return True
|
|
return False
|
|
finally:
|
|
session.close()
|
|
|
|
def mark_as_published(self, draft_id):
|
|
session = self.Session()
|
|
try:
|
|
draft = session.query(Draft).filter_by(id=draft_id).first()
|
|
if draft:
|
|
draft.status = 'published'
|
|
session.commit()
|
|
finally:
|
|
session.close()
|