Apunta los scripts de sync prod al Hetzner nuevo y suma trabajo pendiente
- sync_translations_to_prod.py / sync_audio_to_prod.py / sync_carta_from_prod.py: migran de FEA_PROD_HOST/PASS (CDMON, password) a FEA_PROD_SSH_HOST/PASS + FEA_PROD_DOCKER_CONTAINER (Hetzner/Coolify, auth por clave), con wrapping docker exec y el fix del bug de redirecciones (wc -c/cat) resuelto en el host en vez de dentro del contenedor. - fea_translate_helper.php: subcomando clone_new para clonar en ID local nuevo cuando el ID de prod ya está ocupado localmente. - translate_post.py: --dry-run. - tts_produce.py: --allow-default-voice (voz Nico solo si se permite explícitamente para autores sin voz clonada) + fix voice_for_author. - minimax_tts.py: parámetro speed en t2a/_synth_chunk. - mirror-antiguo/deploy/nginx-mirror.conf: redirects de URLs históricas de catálogo y vista imprimible EFFA. - Importaciones humanas de Pagola (carta 738) + scripts/manifest de la fase A Enrique, y release_issue181_prod.sh / cdmon-retire-fewp1.sh. - .gitignore: excluye docs/backups/ (dumps SQL, mismo motivo que backups/*). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -271,7 +271,8 @@ def save_state(state: dict) -> None:
|
||||
|
||||
|
||||
# ── Orquestación ─────────────────────────────────────────────────────────────
|
||||
def process_post(post_id: int, langs: list[str], status: str, force: bool, state: dict) -> None:
|
||||
def process_post(post_id: int, langs: list[str], status: str, force: bool, state: dict,
|
||||
*, dry_run: bool = False) -> None:
|
||||
src = read_post(post_id)
|
||||
if src.get("lang") and src["lang"] != "es":
|
||||
log(f"#{post_id} no es ES (lang={src['lang']}) — saltado")
|
||||
@@ -286,8 +287,14 @@ def process_post(post_id: int, langs: list[str], status: str, force: bool, state
|
||||
state["done"][key] = existing
|
||||
continue
|
||||
if existing and force:
|
||||
if dry_run:
|
||||
log(f" {lang}: PLAN regenerar traducción previa #{existing}")
|
||||
continue
|
||||
php_helper("unlink", str(post_id), lang)
|
||||
log(f" {lang}: --force, eliminada traducción previa #{existing}")
|
||||
if dry_run:
|
||||
log(f" {lang}: PLAN traducir con {ENGINE} y crear como {status}")
|
||||
continue
|
||||
try:
|
||||
t0 = time.time()
|
||||
title = translate_text(src["title"], lang, is_title=True)
|
||||
@@ -312,6 +319,7 @@ def main() -> int:
|
||||
ap.add_argument("--langs", default="en,fr,it,pt", help="Idiomas destino separados por coma.")
|
||||
ap.add_argument("--status", default="draft", choices=["draft", "publish"], help="Estado de la traducción.")
|
||||
ap.add_argument("--force", action="store_true", help="Regenera aunque ya exista la traducción.")
|
||||
ap.add_argument("--dry-run", action="store_true", help="Muestra el plan sin llamar al LLM ni escribir en WordPress/estado.")
|
||||
args = ap.parse_args()
|
||||
|
||||
langs = [l.strip() for l in args.langs.split(",") if l.strip() in LANG_NAMES]
|
||||
@@ -329,9 +337,11 @@ def main() -> int:
|
||||
|
||||
state = load_state()
|
||||
for pid in ids:
|
||||
process_post(pid, langs, args.status, args.force, state)
|
||||
save_state(state)
|
||||
log(f"FIN. {len(state['done'])} traducciones registradas, "
|
||||
process_post(pid, langs, args.status, args.force, state, dry_run=args.dry_run)
|
||||
if not args.dry_run:
|
||||
save_state(state)
|
||||
mode = "DRY-RUN" if args.dry_run else "FIN"
|
||||
log(f"{mode}. {len(state['done'])} traducciones registradas, "
|
||||
f"{len(state.get('errors', {}))} errores. Estado: {STATE_FILE}")
|
||||
return 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user