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:
@@ -262,6 +262,47 @@ switch ($cmd) {
|
||||
break;
|
||||
}
|
||||
|
||||
case 'clone_new': {
|
||||
// Clona en un ID local NUEVO. Se usa al importar desde prod cuando el
|
||||
// mismo ID ya está ocupado por contenido local distinto.
|
||||
$lang = (string) ($argv[2] ?? '');
|
||||
$status = (string) ($argv[3] ?? '');
|
||||
if ($lang === '') {
|
||||
fwrite(STDERR, "uso: clone_new <lang> <status>\n"); exit(6);
|
||||
}
|
||||
$payload = json_decode(file_get_contents('php://stdin'), true);
|
||||
if (!is_array($payload) || empty($payload['title'])) {
|
||||
fwrite(STDERR, "payload inválido por stdin\n"); exit(4);
|
||||
}
|
||||
$postarr = [
|
||||
'post_title' => wp_slash($payload['title']),
|
||||
'post_content' => wp_slash($payload['content'] ?? ''),
|
||||
'post_excerpt' => wp_slash($payload['excerpt'] ?? ''),
|
||||
'post_status' => $status ?: ($payload['status'] ?? 'draft'),
|
||||
'post_type' => $payload['type'] ?? 'post',
|
||||
'post_author' => (int) ($payload['author'] ?? 1),
|
||||
'post_date' => $payload['date'] ?? current_time('mysql'),
|
||||
'post_date_gmt'=> $payload['date_gmt'] ?? current_time('mysql', true),
|
||||
'post_name' => $payload['slug'] ?? '',
|
||||
'to_ping' => '',
|
||||
'pinged' => '',
|
||||
];
|
||||
$new_id = wp_insert_post($postarr, true);
|
||||
if (is_wp_error($new_id)) { fwrite(STDERR, $new_id->get_error_message() . "\n"); exit(5); }
|
||||
pll_set_post_language($new_id, $lang);
|
||||
$cats = [];
|
||||
foreach ((array) ($payload['cat_slugs'] ?? []) as $slug) {
|
||||
$term = get_term_by('slug', (string) $slug, 'category');
|
||||
if ($term && !is_wp_error($term)) $cats[] = (int) $term->term_id;
|
||||
}
|
||||
if (!$cats) $cats = array_values(array_unique(array_map('intval', (array) ($payload['cats'] ?? []))));
|
||||
wp_set_post_categories($new_id, $cats);
|
||||
set_meta_payload($new_id, normalize_meta_input($payload));
|
||||
clean_post_cache($new_id);
|
||||
echo $new_id;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'carta_sections': {
|
||||
// Descubre el cluster de una carta parseando sus propios enlaces internos
|
||||
// (misma lógica que pinta la portada, fea-carta-portada.php). No depende
|
||||
|
||||
Reference in New Issue
Block a user