Tu Nombre commited on
Commit
5d03516
·
1 Parent(s): c2b1784

fase 1: campo libre + groq parsea config

Browse files
Files changed (1) hide show
  1. main.py +54 -4
main.py CHANGED
@@ -501,6 +501,8 @@ input:focus,select:focus{border-color:#ff2d2d;}
501
  <option value="largo">📺 Video Largo</option>
502
  <option value="short">📱 Short Vertical</option>
503
  </select>
 
 
504
  `;
505
  container.appendChild(div);
506
  }
@@ -542,7 +544,8 @@ async function activar(){
542
  for(let i=1; i<=numCanales; i++){
543
  const n = document.getElementById('nicho'+i);
544
  const t = document.getElementById('tipo'+i);
545
- if(n && t) canales.push({nicho: n.value, tipo: t.value});
 
546
  }
547
  document.getElementById('btn').disabled = true;
548
  document.getElementById('loading').style.display = 'block';
@@ -594,12 +597,57 @@ async def activar_canal(token: str = "", plan: str = ""):
594
  return ACTIVAR_HTML.replace("PLAN_PLACEHOLDER", plan_token).replace("TOKEN_PLACEHOLDER", token).replace("CANALES_PLACEHOLDER", str(PLANES_CANALES.get(plan_token, 1)))
595
  return HTMLResponse("<html><body style='background:#080808;color:#fff;text-align:center;padding:80px'><h1 style='color:#ff2d2d'>Acceso no autorizado</h1><a href='/' style='color:#ff2d2d'>Volver</a></body></html>", status_code=403)
596
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  @app.post("/crear")
598
  async def crear(request: Request):
599
  data = await request.json()
600
  email = data.get("email","").strip().lower()
601
- nicho = data.get("nicho","tecnologia")
602
- tipo = data.get("tipo","largo")
 
 
 
 
 
 
 
603
  token = data.get("token","")
604
  # Verificar token o sesion existente
605
  plan = "basico"
@@ -620,13 +668,15 @@ async def crear(request: Request):
620
  return JSONResponse({"error": "No se pudo crear el canal"}, status_code=500)
621
  u = resultado["url"]
622
  repo = resultado["repo"]
 
 
623
  # Guardar en CLIENTES
624
  if email not in CLIENTES:
625
  CLIENTES[email] = {"canales": [], "plan": plan}
626
  CLIENTES[email]["plan"] = plan
627
  if "canales" not in CLIENTES[email]:
628
  CLIENTES[email]["canales"] = []
629
- CLIENTES[email]["canales"].append({"url": u, "nicho": nicho, "tipo": tipo, "repo": repo, "youtube": False})
630
  guardar_clientes()
631
  # Consumir token si era nuevo
632
  if token in TOKENS_VALIDOS:
 
501
  <option value="largo">📺 Video Largo</option>
502
  <option value="short">📱 Short Vertical</option>
503
  </select>
504
+ <label style="font-size:.85rem;color:#aaa;margin-top:12px;display:block">✨ ¿Tienes alguna preferencia? <span style="color:#666">(opcional)</span></label>
505
+ <textarea id="config${i}" rows="4" placeholder="Ej: voz femenina en ingles, subtitulos grandes arriba, tono motivacional, sin musica..." style="width:100%;padding:12px;background:#080808;color:#fff;border:1px solid #333;border-radius:8px;resize:vertical;font-family:system-ui;margin-top:6px"></textarea>
506
  `;
507
  container.appendChild(div);
508
  }
 
544
  for(let i=1; i<=numCanales; i++){
545
  const n = document.getElementById('nicho'+i);
546
  const t = document.getElementById('tipo'+i);
547
+ const conf = document.getElementById('config'+i);
548
+ if(n && t) canales.push({nicho: n.value, tipo: t.value, config: conf ? conf.value : ""});
549
  }
550
  document.getElementById('btn').disabled = true;
551
  document.getElementById('loading').style.display = 'block';
 
597
  return ACTIVAR_HTML.replace("PLAN_PLACEHOLDER", plan_token).replace("TOKEN_PLACEHOLDER", token).replace("CANALES_PLACEHOLDER", str(PLANES_CANALES.get(plan_token, 1)))
598
  return HTMLResponse("<html><body style='background:#080808;color:#fff;text-align:center;padding:80px'><h1 style='color:#ff2d2d'>Acceso no autorizado</h1><a href='/' style='color:#ff2d2d'>Volver</a></body></html>", status_code=403)
599
 
600
+ async def parsear_config_groq(texto):
601
+ """Parsea instrucciones del cliente con Groq a JSON de configuracion"""
602
+ if not texto or not texto.strip():
603
+ return {}
604
+ try:
605
+ import httpx
606
+ prompt = f"""Analiza las preferencias del cliente y devuelve SOLO un JSON valido con estas keys (omite las que no se mencionen):
607
+ - voz_ia: true/false (si quiere voz IA, default true si no dice nada)
608
+ - voz_genero: "masculina" o "femenina" (default masculina)
609
+ - idioma: "es"/"en"/"pt"/"fr" (default es)
610
+ - velocidad_voz: 0.8 a 1.5 (default 1.0)
611
+ - subir_musica: true/false (default false)
612
+ - subir_voz: true/false (default false)
613
+ - tono: "serio"/"divertido"/"motivacional"/"educativo" (default educativo)
614
+ - subtitulos: true/false (default true)
615
+ - estilo_subtitulos: "tiktok"/"clasico"/"minimal" (default tiktok)
616
+ - color_subtitulos: codigo hex como "#D4AF37" (default #D4AF37)
617
+ - posicion_subtitulos: "arriba"/"centro"/"abajo" (default abajo)
618
+
619
+ Preferencias del cliente: {texto}
620
+
621
+ Responde SOLO el JSON, sin explicaciones, sin markdown."""
622
+ async with httpx.AsyncClient(timeout=20) as cli:
623
+ r = await cli.post("https://api.groq.com/openai/v1/chat/completions",
624
+ headers={"Authorization": f"Bearer {os.environ.get('GROQ_KEY','')}"},
625
+ json={"model":"llama-3.3-70b-versatile","messages":[{"role":"user","content":prompt}],"temperature":0.2}
626
+ )
627
+ txt = r.json()["choices"][0]["message"]["content"].strip()
628
+ # Limpiar markdown si lo trae
629
+ if "```" in txt:
630
+ txt = txt.split("```")[1].replace("json","",1).strip()
631
+ import json
632
+ return json.loads(txt)
633
+ except Exception as e:
634
+ print(f"Error parseando config: {e}", flush=True)
635
+ return {}
636
+
637
+
638
  @app.post("/crear")
639
  async def crear(request: Request):
640
  data = await request.json()
641
  email = data.get("email","").strip().lower()
642
+ canales_data = data.get("canales", [])
643
+ if canales_data:
644
+ nicho = canales_data[0].get("nicho","tecnologia")
645
+ tipo = canales_data[0].get("tipo","largo")
646
+ config_libre = canales_data[0].get("config","").strip()
647
+ else:
648
+ nicho = data.get("nicho","tecnologia")
649
+ tipo = data.get("tipo","largo")
650
+ config_libre = ""
651
  token = data.get("token","")
652
  # Verificar token o sesion existente
653
  plan = "basico"
 
668
  return JSONResponse({"error": "No se pudo crear el canal"}, status_code=500)
669
  u = resultado["url"]
670
  repo = resultado["repo"]
671
+ # Parsear preferencias del cliente con Groq
672
+ config_parsed = await parsear_config_groq(config_libre)
673
  # Guardar en CLIENTES
674
  if email not in CLIENTES:
675
  CLIENTES[email] = {"canales": [], "plan": plan}
676
  CLIENTES[email]["plan"] = plan
677
  if "canales" not in CLIENTES[email]:
678
  CLIENTES[email]["canales"] = []
679
+ CLIENTES[email]["canales"].append({"url": u, "nicho": nicho, "tipo": tipo, "repo": repo, "youtube": False, "config": config_parsed, "config_texto": config_libre})
680
  guardar_clientes()
681
  # Consumir token si era nuevo
682
  if token in TOKENS_VALIDOS: