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}`)
  }
})