Más notas sobre importar posts

Minientrada

Retomo el tema importar entradas en WordPress de forma masiva.

Recientemente volví a tirar de ese script para traerme un JSON con tweets viejos a danirod.es. Ni siquiera los he hecho públicos. Por el momento sólo los he hecho privados porque lo que me interesa es tenerlos consolidados. Tampoco son tweets recientes; estamos hablando de tweets que tienen más de una década. Todos los enlaces externos dan HTTP 404, están fatal escritos y, en general, es contenido poco interesante para internet. Pero me apetecía tenerlos a mano.

Uso el plugin Syndication Links para conectar entradas que sean importadas de otras redes sociales con su URL de referencia; las sindicaciones de Hacker News son un ejemplo. En el caso de tweets de una cuenta que ya ni siquiera existe, es bastante irrelevante plantar un u-syndication. Aun así, me apetecía ponerlo.

En el caso del plugin Syndication Links, la metadata sobre sindicación se guarda como un campo personalizado de WordPress llamado mf2_syndication. Con la API XML-RPC de WordPress es posible crear campos personalizados rellenando el array custom_fields. Hay que tener en cuenta que no es un clave-valor simple, sino que es un array de objetos, con su campo key para el título del campo, y su campo value para el valor del campo. En el módulo de npm, los campos se dan usando la key customFields en la llamada a newPost:

client.newPost({
  title: '...',
  content: '...',
  customFields: [
    { key: 'field-1', value: 'value value' },
    { key: 'field-2', value: 'more value more value' }
  ]
}, (e, id) => console.log(e, id));

Consideraciones sobre el volcado de posts

Minientrada

A raíz del volcado de posts que cargué el otro día estoy considerando próximos datasets a importar. Exports procedentes de la GDPR, viejas entradas de blog sacadas de Wayback Archive, incluso tal vez puede que crosspost de cosas cargadas a YouTube o Twitter (algo que llevo años persiguiendo).

Algunas consideraciones técnicas que he aprendido para la próxima:

  • Es mejor usar un entorno de staging mientras se hacen pruebas para no ensuciar el sitio web, porque lo más posible es que falle al principio.
  • Por lo tanto, es mejor ir de poco en poco, y no intentar importar un dataset muy grande hasta que no se ensaye con algo más pequeño que se pueda borrar fácilmente si se hace mal.
  • Por si hay que borrar, es mejor ponerles a los posts importados una etiqueta nueva para poder filtrar fácilmente posts con esa etiqueta y borrar todo. En mi caso, esa etiqueta ha sido hn-import.
  • Si el blog lo alojas por tu cuenta, no tienes que dar parte del API Rate Limit a nadie, pero corres el riesgo de causarte un ataque de denegación de servicio a ti mismo. Como casi hago, de hecho, porque mi código JavaScript intentó lanzar las 49 peticiones HTTP POST a la vez.
  • Por asociación de ideas, mejor apagar los hooks externos que se llaman al crear posts mientras se estén importando cosas. No pingbacks, no trackbacks, no webmentions, no ActivityPub. (Aparte que muchos de estos posts tienen unos cuantos años y no tiene mucho sentido generar notificaciones por esto.)
  • El feed RSS va a sufrir.

El problema, como ya he dicho alguna vez, son los títulos. Muchas redes sociales no usan títulos en sus publicaciones, pero algo hay que poner para que la sindicación por RSS o al usar temas y widgets de WordPress que traten de mostrar el título de un post, tenga o no, puedan mostrar algo distinto a (sin título).

Importando de redes sociales con XML-RPC

Minientrada

Una de las cosas bonitas de la GDPR es que casi obliga a las redes sociales y sitios similares a tener un sistema de exportado de datos. Y casi siempre lo hacen con algún formato estructurado como CSV, JSON o XML, fácil de procesar por un ordenador.

Paralelamente, WordPress tiene el viejo confiable XML-RPC para crear posts de forma programática. Si no tienes mucha idea, recomiendan cerrar ese endpoint al exterior para evitar problemas. Pero en verdad, si sabes protegerlo, resulta muy práctico para crear posts a golpe de petición HTTP. (En teoría existe la API REST, pero bueno…)

Con la ayuda de un cliente XML-RPC para WordPress que hay en NPM y de la API de Hacker News, hice en Node.js un script de un solo uso que crease una entrada por cada comentario y enlace enviado para enlazar hacia el comentario o la historia, siguiendo el modelo de sindicación PESOS de IndieWeb (Publish Elsewhere, Syndicate to Own Site). Le he puesto la etiqueta hn-import a la colección. ¿Cuál será el próximo archivo que importe?

En sí la librería no es muy complicada de utilizar. Una vez tienes un cliente conectado es muy fácil chutarle un array de posts a crear (por ejemplo, procesar fila a fila un CSV o item a item un JSON o un XML). Primero se crea un cliente:

const { createClient } = require("wordpress")

const client = createClient({
  url: "https://example.com",
  username: "mi user",
  password: "mi password"
})

Luego definiendo el payload. Aquí es donde encuentro más cómodo crear un objeto JSON que declarar todo el chorizo XML de XML-RPC:

const payload = {
  title: "El título de mi entrada",
  content: `
    <p>El contenido de mi entrada.</p>
    <blockquote>Aceptamos HTML.</blockquote>
    <p><a href="https://www.example.com">Y enlaces</a></p>
  `.trim(),
  status: 'publish', // podría ser 'draft' o 'private'
  termNames: {
    category: ['Categoría'],
    post_tag: ['tag 1', 'tag 2', 'tag 3'],
  },
  date: '2006-01-02 15:04:05',
  format: 'link' // podría ser 'aside', 'status', 'photo', ...
}

Y ya postear usando newPost. La librería es previa a promesas así que su único punto malo es que está orientada a callbacks.

client.newPost(payload, (err, id) => {
  if (err) {
    console.error(err)
  } else {
    console.log(`ID del nuevo post: ${id}`)
  }
})

WordPress vintage

Imagen

Aprovechando que WordPress cumplió 18 años la semana pasada, me he decidido a instalar el clásico tema Default, el que fue el tema por defecto hasta la llegada de los temas “Twenty”.

Por supuesto, Default no es un tema pensado para móviles. No tiene menús integrados (he tenido que traerme la navegación a la sección widgets). Sorprendentemente, se lleva bien con Gutenberg, aunque no tiene soporte para post formats por lo que no puedo marcar una entrada como “Minientrada”, ni como “Estado”, ni como ninguna de esas cosas que vinieron después, ya en la era Twenty, con temas compatibles con móvil, y con un diseño que roza lo brutalista, basado en colores fuertes, pocas decoraciones y tipografías grandes.

Pongo esta captura de pantalla como evidencia por si en algún momento decido regresar a algo un poco más moderno.

Notitas de seguridad para WordPress

Minientrada

La extensión Two Factor es un must. WordPress está detrás de ella y es open source, por lo que en principio debería estar libre de chantajes, modo PRO y demás cosas. Hace lo que tiene que hacer: te pide que introduzcas un código de 6 dígitos con una aplicación TOTP que estés utilizando.

Two Factor te desactiva, desafortunadamente, el acceso XML-RPC y el WP-JSON. Hay quien tiene sus concerns y ve bien apagar esas APIs, pero por otra parte yo sí las quiero para poder automatizar cosas con WordPress. Esto lo tengo solucionado con dos cosas:

  • Con la extensión Application Passwords (que deja de ser necesario en WordPress 5.6 porque ya viene preinstalada), se pueden crear passwords especiales para poder crear integraciones con contraseñas aleatorias sin tener que darles nuestra propia contraseña.
  • Este snippet PHP para inhibir el Two Factor cuando se usa una Application Password. (De otro modo, las Application Password también tratarían de pedir un token 2FA, lo cual no es posible al automatizar.)

Recomendaría también extensiones que prevengan ataques por fuerza bruta. La que yo uso inhibe el login si se introduce mal la contraseña varias veces, tanto por wp-login como por XML-RPC. Me quedaría conectarlo con el cortafuegos para bloquear directamente las IPs problemáticas, pero eso es un asunto para otro momento.

Probando a publicar desde la app de WordPress

Estado

Probando a publicar desde la app de WordPress. Yo es que tampoco pido tanto ya. Algo que me deje publicar sobre la marcha sin fricción. No quiero commits de Git, no quiero contraseñas en un navegador ni tokens 2FA a cada vez que abra el panel. Quiero un botón en la hoja para compartir y con suerte integración con atajos de iOS. 😫

Contraseña olvidada

Estado

Alguien se olvidó de su contraseña para entrar al panel de control del blog. Como por supuesto no tengo configurado el e-mail en este sitio web, hasta hoy no he tenido tiempo o voluntad de entrar en la base de datos y seguir el procedimiento de emergencia para recuperar la contraseña.

Moraleja de la historia: si la contraseña no está en el KeePass (y sincronizada a al menos un dispositivo), la contraseña no existe.

Los enlaces guays no caducan

Minientrada

De momento me está gustando el cambio del software de mi página web a WordPress. Puedo darle a lo de escribir todos los días un rato si me apetece sin encender mi ordenador, accediendo al wp-admin (el panel de control) directamente desde mi iPad.

Cuando la semana pasada hice el reboot, tiré abajo todo el sitio web y levanté otro completamente en blanco. A primera vista parece que estoy aniquilando y eliminando de internet todo lo que he escrito en los últimos 6 años con el viejo software de mi web. Pero en realidad no. No me gusta el link rotting, y por supuesto en mi sitio web no se va a tolerar link rotting.

Por eso cuando la semana pasada cambié el software de mi web pasé tanto tiempo configurando reglas en el proxy inverso que tiene la máquina que sirve www.danirod.es y otros 6 sitios web. (Se entiende ahora por qué a principios de año metí un Traefik para que me intentase echar una mano y no perder la cabeza.)

Si sigues un enlace viejo a www.danirod.es, como el que puedes tener en marcadores desde ni se sabe cuánto, o el que puedes encontrar en algún tweet viejo, o en un buscador, ese enlace seguirá funcionando y enseñando contenido, incluso aunque haya sido barrido con el cambio de software. Haz la prueba, mira qué enlace tan sexy y numérico escrito en 2019 tengo por aquí: https://www.danirod.es/2019/084/1553504854.

Un enlace a algo que haya publicado en esta página nunca puede dar HTTP 404. Si se ha escrito, tiene que estar. Como mucho, puede haber cambiado de dirección URL. De modo que si finalmente no “devuelvo” el nuevo software de mi web y sigo usando WordPress, una vez traiga el historial con todo lo que escribí en años anteriores, mantendré una tabla de traducción para que visitar el enlace que he pasado antes te mande a la nueva dirección del post.

Reboot

Al final, la casualidad ha hecho que el Dani de 2020 siga teniendo bastantes cosas en común con el Dani de 2010. Salir poco de casa, tener un profundo odio por el gobierno, y un gusto por auto-torturarse con WordPress difícil de entender.

– Yo mismo, anoche a la 1:00 mientras terminaba de meter reglas en el Traefik de danirod.es.

Pues finalmente he hecho un reboot a mi sitio web y he empezado de cero. Es una sensación parecida a como cuando en clase tocaba estrenar cuaderno. Tengo un lienzo en blanco, y ahora hay que rellenarlo con cosas.

Para esta etapa, he cambiado el software de mi web y ahora escribo con WordPress. Ha evolucionado mucho en estos cinco años y tengo curiosidad por probar las novedades. Si viese que me da demasiados problemas, me desharía de él y volvería a algo como lo de antes. Yo lo único que quiero es no complicarme la vida; me da igual el software que haga funcionar mi página web.

Ahora una pequeña nota al pie técnica para interesados: ¿por qué? ¿acaso ya no me gusta Jekyll, el software que usaba hasta ahora para mantener mi web? Sí, me gusta, y funciona estupendamente. El problema con la antigua web era más mío que del software. Hace un par de años empecé a llenar el blog de cosas que no eran artículos, como fotos, vídeos, hasta estadísticas de mis entrenamientos. Todos estos extras estaban montados casi con cinta adhesiva metiendo docenas de plantillas y hacks en el sitio web. Pero la cinta adhesiva a veces tiene estas cosas: que se despega. Y muchas veces algo que debía tomar dos minutos, como puede ser etiquetar y subir una foto al blog, toma tres horas porque he encontrado un error nuevo; eso cuando decido sentarme a arreglarlo y no desisto directamente.

Entonces, aunque sigo metido en esta etapa post-redes sociales en la que el objetivo es dejar de alimentar los engranajes de Twitter y redes similares y ser mi propia república independiente en internet, voy a intentar limitarme con lo que escribo en mi sitio web a cosas sencillas que sepa que van a funcionar siempre. Porque, de nuevo, yo lo único que quiero es no complicarme la vida.