Spaces:
Running
Running
deploy from github actions
Browse files- app/routers/lyrics.py +20 -3
- app/routers/songs.py +25 -6
- app/routers/workers.py +1 -0
- tasks.py +15 -4
app/routers/lyrics.py
CHANGED
|
@@ -374,7 +374,7 @@ def update_lyric(
|
|
| 374 |
def delete_lyric(lyric_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
|
| 375 |
db_lyric = db.query(Lyric).filter(Lyric.id == lyric_id).first()
|
| 376 |
if not db_lyric:
|
| 377 |
-
raise HTTPException(status_code=404, detail="
|
| 378 |
|
| 379 |
is_authorized = False
|
| 380 |
if db_lyric.created_by == current_user.id:
|
|
@@ -395,18 +395,35 @@ def delete_lyric(lyric_id: int, db: Session = Depends(get_db), current_user: Use
|
|
| 395 |
break
|
| 396 |
|
| 397 |
if not is_authorized:
|
| 398 |
-
raise HTTPException(
|
|
|
|
|
|
|
|
|
|
| 399 |
|
| 400 |
shared_group_ids = list(db_lyric.group_ids)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 401 |
db.delete(db_lyric)
|
| 402 |
db.commit()
|
|
|
|
| 403 |
for gid in shared_group_ids:
|
| 404 |
try:
|
| 405 |
from app.routers.alabanza import broadcast_to_group
|
| 406 |
broadcast_to_group(gid, {"type": "group_updated", "grupo_id": gid}, db)
|
| 407 |
except Exception:
|
| 408 |
pass
|
| 409 |
-
return {"message": "
|
| 410 |
|
| 411 |
|
| 412 |
|
|
|
|
| 374 |
def delete_lyric(lyric_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
|
| 375 |
db_lyric = db.query(Lyric).filter(Lyric.id == lyric_id).first()
|
| 376 |
if not db_lyric:
|
| 377 |
+
raise HTTPException(status_code=404, detail="Letra no encontrada")
|
| 378 |
|
| 379 |
is_authorized = False
|
| 380 |
if db_lyric.created_by == current_user.id:
|
|
|
|
| 395 |
break
|
| 396 |
|
| 397 |
if not is_authorized:
|
| 398 |
+
raise HTTPException(
|
| 399 |
+
status_code=403,
|
| 400 |
+
detail="No tienes permisos para eliminar esta letra. Solo el creador o un administrador del grupo pueden eliminarla."
|
| 401 |
+
)
|
| 402 |
|
| 403 |
shared_group_ids = list(db_lyric.group_ids)
|
| 404 |
+
if db_lyric.group_id is not None and db_lyric.group_id not in shared_group_ids:
|
| 405 |
+
shared_group_ids.append(db_lyric.group_id)
|
| 406 |
+
|
| 407 |
+
# 1. Limpiar asociaciones en repertorios
|
| 408 |
+
db.query(RepertorioLyric).filter(RepertorioLyric.lyric_id == lyric_id).delete()
|
| 409 |
+
|
| 410 |
+
# 2. Desvincular letras hijas si existieran
|
| 411 |
+
db.query(Lyric).filter(Lyric.parent_lyric_id == lyric_id).update({"parent_lyric_id": None})
|
| 412 |
+
|
| 413 |
+
# 3. Limpiar asociaciones secundarias de grupos
|
| 414 |
+
db_lyric.groups_shared.clear()
|
| 415 |
+
|
| 416 |
+
# 4. Eliminar la letra
|
| 417 |
db.delete(db_lyric)
|
| 418 |
db.commit()
|
| 419 |
+
|
| 420 |
for gid in shared_group_ids:
|
| 421 |
try:
|
| 422 |
from app.routers.alabanza import broadcast_to_group
|
| 423 |
broadcast_to_group(gid, {"type": "group_updated", "grupo_id": gid}, db)
|
| 424 |
except Exception:
|
| 425 |
pass
|
| 426 |
+
return {"message": "Letra eliminada correctamente"}
|
| 427 |
|
| 428 |
|
| 429 |
|
app/routers/songs.py
CHANGED
|
@@ -419,6 +419,18 @@ async def subir_cancion(
|
|
| 419 |
actual_size = os.path.getsize(upload_path)
|
| 420 |
logger.info(f"[{task_id}] Archivo guardado: {file.filename} ({actual_size / (1024*1024):.2f}MB)")
|
| 421 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
# ==========================================
|
| 423 |
# CREAR REGISTRO EN BASE DE DATOS
|
| 424 |
# ==========================================
|
|
@@ -447,6 +459,7 @@ async def subir_cancion(
|
|
| 447 |
nuevo_proceso = db.query(Task).filter(Task.task_id == task_id).first()
|
| 448 |
if nuevo_proceso:
|
| 449 |
nuevo_proceso.status = "pending"
|
|
|
|
| 450 |
nuevo_proceso.telegram_file_ids = None
|
| 451 |
nuevo_proceso.folder = None
|
| 452 |
nuevo_proceso.song_name = song_name_val
|
|
@@ -461,6 +474,7 @@ async def subir_cancion(
|
|
| 461 |
artist=artist_val,
|
| 462 |
stems=stems,
|
| 463 |
status="pending",
|
|
|
|
| 464 |
consumed_credit_type=consumed_type
|
| 465 |
)
|
| 466 |
db.add(nuevo_proceso)
|
|
@@ -475,8 +489,8 @@ async def subir_cancion(
|
|
| 475 |
# ==========================================
|
| 476 |
queue_name = get_user_routing_queue(db, current_user.id)
|
| 477 |
kwargs_async = {
|
| 478 |
-
"args": [upload_path, task_id, stems, trim_start, trim_end],
|
| 479 |
-
"kwargs": {"auto_harmonize": auto_harmonize},
|
| 480 |
"task_id": task_id
|
| 481 |
}
|
| 482 |
if queue_name:
|
|
@@ -1421,13 +1435,18 @@ async def limpiar_tarea(
|
|
| 1421 |
except Exception as e:
|
| 1422 |
logger.warning(f"Error general al limpiar archivos de {task_id}: {e}. Se continuará con el borrado en BD.")
|
| 1423 |
|
| 1424 |
-
# Eliminar stems de Hugging Face Dataset si existen
|
| 1425 |
try:
|
| 1426 |
-
from app.utils.hf_storage import delete_folder_from_hf
|
| 1427 |
delete_folder_from_hf(f"stems/{task_id}")
|
| 1428 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1429 |
except Exception as e:
|
| 1430 |
-
logger.warning(f"Error eliminando
|
| 1431 |
|
| 1432 |
# Eliminar pista original y stems de Supabase storage
|
| 1433 |
try:
|
|
|
|
| 419 |
actual_size = os.path.getsize(upload_path)
|
| 420 |
logger.info(f"[{task_id}] Archivo guardado: {file.filename} ({actual_size / (1024*1024):.2f}MB)")
|
| 421 |
|
| 422 |
+
# ==========================================
|
| 423 |
+
# SUBIDA A HUGGING FACE DATASET (COSTO $0 / EGRESS ILIMITADO)
|
| 424 |
+
# ==========================================
|
| 425 |
+
cloud_url = None
|
| 426 |
+
try:
|
| 427 |
+
from app.utils.hf_storage import upload_to_hf
|
| 428 |
+
hf_orig_key = f"originals/{task_id}_{safe_filename}"
|
| 429 |
+
cloud_url = upload_to_hf(upload_path, hf_orig_key)
|
| 430 |
+
logger.info(f"[{task_id}] Audio original subido a Hugging Face Dataset: {cloud_url}")
|
| 431 |
+
except Exception as hfe:
|
| 432 |
+
logger.warning(f"[{task_id}] No se pudo subir original a Hugging Face: {hfe}. Se procesará de forma local si aplica.")
|
| 433 |
+
|
| 434 |
# ==========================================
|
| 435 |
# CREAR REGISTRO EN BASE DE DATOS
|
| 436 |
# ==========================================
|
|
|
|
| 459 |
nuevo_proceso = db.query(Task).filter(Task.task_id == task_id).first()
|
| 460 |
if nuevo_proceso:
|
| 461 |
nuevo_proceso.status = "pending"
|
| 462 |
+
nuevo_proceso.cloud_url = cloud_url
|
| 463 |
nuevo_proceso.telegram_file_ids = None
|
| 464 |
nuevo_proceso.folder = None
|
| 465 |
nuevo_proceso.song_name = song_name_val
|
|
|
|
| 474 |
artist=artist_val,
|
| 475 |
stems=stems,
|
| 476 |
status="pending",
|
| 477 |
+
cloud_url=cloud_url,
|
| 478 |
consumed_credit_type=consumed_type
|
| 479 |
)
|
| 480 |
db.add(nuevo_proceso)
|
|
|
|
| 489 |
# ==========================================
|
| 490 |
queue_name = get_user_routing_queue(db, current_user.id)
|
| 491 |
kwargs_async = {
|
| 492 |
+
"args": [upload_path if not queue_name else "", task_id, stems, trim_start, trim_end],
|
| 493 |
+
"kwargs": {"cloud_url": cloud_url, "auto_harmonize": auto_harmonize},
|
| 494 |
"task_id": task_id
|
| 495 |
}
|
| 496 |
if queue_name:
|
|
|
|
| 1435 |
except Exception as e:
|
| 1436 |
logger.warning(f"Error general al limpiar archivos de {task_id}: {e}. Se continuará con el borrado en BD.")
|
| 1437 |
|
| 1438 |
+
# Eliminar stems y archivos de Hugging Face Dataset si existen
|
| 1439 |
try:
|
| 1440 |
+
from app.utils.hf_storage import delete_folder_from_hf, delete_from_hf
|
| 1441 |
delete_folder_from_hf(f"stems/{task_id}")
|
| 1442 |
+
if task_record.cloud_url and "/originals/" in task_record.cloud_url:
|
| 1443 |
+
import re as _re
|
| 1444 |
+
_m = _re.search(r'/resolve/main/(originals/.+)$', task_record.cloud_url)
|
| 1445 |
+
if _m:
|
| 1446 |
+
delete_from_hf(_m.group(1))
|
| 1447 |
+
logger.info(f"[{task_id}] Stems y archivos eliminados de Hugging Face por eliminación explícita.")
|
| 1448 |
except Exception as e:
|
| 1449 |
+
logger.warning(f"Error eliminando archivos de Hugging Face: {e}")
|
| 1450 |
|
| 1451 |
# Eliminar pista original y stems de Supabase storage
|
| 1452 |
try:
|
app/routers/workers.py
CHANGED
|
@@ -410,6 +410,7 @@ def agent_poll(
|
|
| 410 |
return {
|
| 411 |
"command": current_command,
|
| 412 |
"is_active": worker.is_active,
|
|
|
|
| 413 |
"user_id": worker.user_id,
|
| 414 |
"status": worker.status
|
| 415 |
}
|
|
|
|
| 410 |
return {
|
| 411 |
"command": current_command,
|
| 412 |
"is_active": worker.is_active,
|
| 413 |
+
"is_public": bool(getattr(worker, "is_public", False)),
|
| 414 |
"user_id": worker.user_id,
|
| 415 |
"status": worker.status
|
| 416 |
}
|
tasks.py
CHANGED
|
@@ -789,7 +789,7 @@ def procesar_cancion_completa(self, file_path, task_id, stems, trim_start="", tr
|
|
| 789 |
# DESCARGA DE SUPABASE (CLOUD QUEUE)
|
| 790 |
# ==========================================
|
| 791 |
if cloud_url:
|
| 792 |
-
logger.info(f"[{task_id}] Descargando audio desde
|
| 793 |
self.update_state(state='PROGRESS', meta={'progress': 1, 'message': 'Preparando pista...'})
|
| 794 |
|
| 795 |
UPLOADS_DIR = os.getenv("UPLOADS_DIR", os.path.join(os.path.dirname(os.path.abspath(__file__)), "uploads"))
|
|
@@ -802,9 +802,20 @@ def procesar_cancion_completa(self, file_path, task_id, stems, trim_start="", tr
|
|
| 802 |
with open(file_path, 'wb') as f:
|
| 803 |
for chunk in response.iter_content(chunk_size=8192):
|
| 804 |
f.write(chunk)
|
| 805 |
-
logger.info(f"[{task_id}] Archivo
|
| 806 |
|
| 807 |
-
# Eliminar archivo original de
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 808 |
try:
|
| 809 |
from app.utils.supabase_storage import delete_supabase_file, parse_supabase_path
|
| 810 |
orig_path = parse_supabase_path(cloud_url)
|
|
@@ -812,7 +823,7 @@ def procesar_cancion_completa(self, file_path, task_id, stems, trim_start="", tr
|
|
| 812 |
delete_supabase_file(orig_path)
|
| 813 |
logger.info(f"[{task_id}] Archivo original de Supabase storage eliminado.")
|
| 814 |
except Exception as e:
|
| 815 |
-
|
| 816 |
|
| 817 |
# ==========================================
|
| 818 |
# DESCARGA DE YOUTUBE (SI APLICA)
|
|
|
|
| 789 |
# DESCARGA DE SUPABASE (CLOUD QUEUE)
|
| 790 |
# ==========================================
|
| 791 |
if cloud_url:
|
| 792 |
+
logger.info(f"[{task_id}] Descargando audio desde la nube (Cola Offline / HF): {cloud_url}")
|
| 793 |
self.update_state(state='PROGRESS', meta={'progress': 1, 'message': 'Preparando pista...'})
|
| 794 |
|
| 795 |
UPLOADS_DIR = os.getenv("UPLOADS_DIR", os.path.join(os.path.dirname(os.path.abspath(__file__)), "uploads"))
|
|
|
|
| 802 |
with open(file_path, 'wb') as f:
|
| 803 |
for chunk in response.iter_content(chunk_size=8192):
|
| 804 |
f.write(chunk)
|
| 805 |
+
logger.info(f"[{task_id}] Archivo descargado con éxito.")
|
| 806 |
|
| 807 |
+
# Eliminar archivo original temporal de Hugging Face tras descarga
|
| 808 |
+
try:
|
| 809 |
+
from app.utils.hf_storage import delete_from_hf
|
| 810 |
+
import re as _re
|
| 811 |
+
_m = _re.search(r'/resolve/main/(originals/.+)$', cloud_url)
|
| 812 |
+
if _m:
|
| 813 |
+
delete_from_hf(_m.group(1))
|
| 814 |
+
logger.info(f"[{task_id}] Archivo original temporal de Hugging Face eliminado: {_m.group(1)}")
|
| 815 |
+
except Exception as _hfe:
|
| 816 |
+
logger.warning(f"[{task_id}] Error al eliminar original temporal de Hugging Face tras descarga: {_hfe}")
|
| 817 |
+
|
| 818 |
+
# Eliminar archivo original de Supabase (legacy fallback)
|
| 819 |
try:
|
| 820 |
from app.utils.supabase_storage import delete_supabase_file, parse_supabase_path
|
| 821 |
orig_path = parse_supabase_path(cloud_url)
|
|
|
|
| 823 |
delete_supabase_file(orig_path)
|
| 824 |
logger.info(f"[{task_id}] Archivo original de Supabase storage eliminado.")
|
| 825 |
except Exception as e:
|
| 826 |
+
pass
|
| 827 |
|
| 828 |
# ==========================================
|
| 829 |
# DESCARGA DE YOUTUBE (SI APLICA)
|