Si audio.play() fallaba tras verificar el hash (p.ej. política de autoplay del navegador tras el await de fetch+digest), el aviso "No se pudo verificar el audio" quedaba fijo en pantalla aunque el usuario reprodujera el audio a mano desde los controles nativos que ya estaban visibles. El evento 'play' real del <audio> ahora limpia ese aviso y oculta el botón, sea cual sea el camino por el que arrancó la reproducción. Reportado por Rafa en el canal feadulta, viendo el estado atascado en "Más allá de la trinchera..." (post 56196) tras el bloqueo 403 de Cloudflare.
feadulta — WordPress
Código del sitio WordPress de feadulta.com. Plugins personalizados (mu-plugins) y scripts de migración y mantenimiento.
Estructura
mu-plugins/ — plugins WordPress cargados automáticamente (sin activar)
scripts/ — scripts Python/PHP de migración, traducción, TTS y mantenimiento
mu-plugins principales
| Plugin | Función |
|---|---|
fea-carta-portada.php |
Parser de la carta semanal → portada |
fea-homepage.php |
Tarjetas de portada |
fea-share.php |
Sección "Comparte FeAdulta" (Facebook, Instagram, Imprimir) |
fea-ui.php |
Estilos globales, menú, fondo cálido en artículos |
fea-accesibilidad.php |
Tipografía Atkinson Hyperlegible (self-hosted) + toggle claro/oscuro persistente |
fea-beta-feedback.php |
Barra de feedback beta + endpoint /fea/v1/lang/{id} |
fea-search.php |
Buscador móvil nativo |
fea-pensamientos.php |
Widget de pensamientos |
carta-semana-plugin.php |
Redirects carta vigente/semana pasada |
Scripts principales
| Script | Función |
|---|---|
import_new_k2_items.py |
Importar artículos nuevos desde Joomla/K2 |
import_new_cartas.py |
Importar cartas semanales nuevas |
translate_haiku.py |
Traducción automática vía Claude Haiku |
tts_produce.py |
Generación de audio TTS (MiniMax) |
sync_translations_to_prod.py |
Sincronizar traducciones local → producción |
sync_audio_to_prod.py |
Sincronizar UN post/carta de audio TTS local → producción (sube el mp3, verifica SHA-256 remoto y persiste fea_audio_sha256) |
sync_audio_bulk.sh |
Envoltorio de sync_audio_to_prod.py para lotes: para en el primer fallo, sin reintentos ciegos, resumen ok/skip |
detect_untranslated.php |
Detectar posts sin traducir |
Sincronizar audio TTS a producción (local → prod)
sync_audio_to_prod.py sube el mp3 de UN post/carta y, desde el #213, calcula y verifica el
SHA-256 en cada subida (reproducción verificada automática, sin backfill manual — ver #212).
Para lotes de varios posts, usar sync_audio_bulk.sh: es el envoltorio que añade "parar en el
primer fallo" (el script Python no lo hace por sí solo, recorre toda la lista y acumula errores).
Carga los IDs con mapfile/mediante array y redirige el stdin de cada invocación a /dev/null a
propósito — un while read id; do ...ssh...; done < fichero sin esa precaución se rompe en
silencio porque ssh se come el resto del fichero de IDs (ver
feedback-bash-while-read-ssh-stdin en la memoria del proyecto).
export FEA_PROD_SSH_HOST="rafa@188.40.120.157"
export FEA_PROD_DOCKER_CONTAINER="wordpress-r2ssjifwj0r0ghyoqd528uaa"
# Dry-run primero, siempre
scripts/sync_audio_bulk.sh --ids 55519,55520,822 --dry-run
# Aplicar de verdad
scripts/sync_audio_bulk.sh --ids 55519,55520,822
# Desde un fichero (un ID por línea) o toda la cola de una carta
scripts/sync_audio_bulk.sh --file /tmp/ids_pendientes.txt
scripts/sync_audio_bulk.sh --carta 54254
Rollback de un post concreto: python3 scripts/sync_audio_to_prod.py --rollback --ids <id>
(borra el meta en prod, no toca el mp3 local).
Servidor local de desarrollo
WordPress corre en Docker local, accesible vía Tailscale:
https://farmer.taild3aaf6.ts.net/fea/
Admin: eqpyk / NuevaFeAdulta2024!