Migrar un foro del plugin bbPress de WordPress a Discourse

Recientemente realicé con éxito una migración de base de datos de bbPress utilizando el script de migración integrado de Discourse. Ahora lo compartiré como un tutorial paso a paso.

Nota: Este tutorial es para el plugin bbPress, no para la versión independiente heredada de bbPress.

¿Qué datos se pueden importar?

  • Usuarios (incluidos los usuarios anónimos)
  • Categorías
  • Temas
  • Publicaciones
  • Mensajes privados (a través de BuddyPress)
  • Archivos adjuntos
  • Enlaces permanentes (Permalinks)

Antes de iniciar la migración, configure un entorno de desarrollo en su máquina (o dentro de una máquina virtual) y ejecute la importación allí en lugar de dentro del contenedor Docker. Cuando lo intenté dentro del contenedor Docker, obtuve el problema peer authentication failed. Por lo tanto, le recomiendo encarecidamente que utilice una máquina de desarrollo. Consulte la guía de instalación para desarrollo en macOS o Ubuntu / Debian.

Discourse requiere Ruby 3.4 o superior. Puede verificar su versión de Ruby con:

ruby -v

Ahora necesitamos instalar la dependencia libmysqlclient-dev para poder usar el gem mysql2.

sudo apt-get install libmysqlclient-dev

Después de la instalación exitosa, vaya a la ruta de su instalación de desarrollo de Discourse (típicamente ~/discourse).

cd ~/discourse

Configurando la conexión a la base de datos

El script de importación de bbPress lee toda la configuración de conexión a la base de datos desde variables de entorno. No es necesario editar el archivo del script. Se admiten las siguientes variables de entorno:

Variable Valor predeterminado Descripción
BBPRESS_HOST localhost Host de la base de datos MySQL
BBPRESS_USER root Nombre de usuario de MySQL
BBPRESS_PW (vacío) Contraseña de MySQL
BBPRESS_DB bbpress Nombre de la base de datos MySQL
BBPRESS_PREFIX wp_ Prefijo de tabla de WordPress
BBPRESS_ATTACHMENTS_DIR /ruta/a/adjuntos Ruta al directorio de archivos adjuntos de bbPress

Si está migrando su base de datos desde localhost, generalmente solo necesita establecer el nombre de la base de datos:

IMPORT=1 bundle \u0026\u0026 IMPORT=1 BBPRESS_DB="mi_bbpress" bundle exec ruby script/import_scripts/bbpress.rb

Si está migrando su base de datos desde un servidor externo, también necesitará establecer el host, el nombre de usuario y la contraseña:

IMPORT=1 bundle \u0026\u0026 IMPORT=1 BBPRESS_HOST="NOMBRE_HOST_REMOTO" BBPRESS_USER="NOMBRE_USUARIO_DB" BBPRESS_PW="MI_CONTRASENA_SEGURA" BBPRESS_DB="NOMBRE_DB" bundle exec ruby script/import_scripts/bbpress.rb

¡Felicitaciones! Su base de datos se migró con éxito de bbPress a Discourse :clap: :wave: :boom:

Ahora tome una copia de seguridad desde la página de administración /admin/backups e impórtela en su sitio web de Discourse en vivo.


Después de mover su foro de bbPress a Discourse, si aún va a usar su sitio web de WordPress como sitio principal y desea conectarlo con Discourse, instale el plugin oficial de WordPress de Discourse.

15 Me gusta

Just wanted to thank you for providing this step-by-step guide. We migrated our site from bbpress to Discourse with minimal headache thanks to you. Since we’re running multisite wordpress there were a few tweaks to make to the importer, but other than that it went very smoothly. Thanks!

3 Me gusta

If you can share your tweaks then it will be helpful to other multisite owners.

1 me gusta

Admittedly I didn’t take very good notes, and have since killed the VM it
was on (sorry!) but the basic gist is that if your bbpress install is not
on the primary site of the Multisite setup you’ll need to a) set the
environmental variable for BBPRESS_PREFIX to include your site’s ID number
(e.g. wp_6_ ) and then edit the migration script to use wp_users rather
than #{BBPRESS_PREFIX} for the Users sql. This is because on Multisite
installations the wp_users table is shared across sites and then each site
has its own tables for posts, postmeta, etc.

5 Me gusta

thanks for the details :thumbsup:

I recently posted on how to import bbpress into discourse

2 Me gusta

Great job on the tutorial! But it’s confusing to have two different guides on this. Do they serve different purposes? Otherwise we should figure out how to merge them.

That guide is about how to import bbpress inside of a development environment, mine is how to import bbpress using the docker container. It’s just 2 different ways to go. I’d recommend importing via docker container since it doesn’t ask for the additional step of setting up a development environment, which can be cumbersome.

Hello I am stuck trying to import successfully after all users are done importing.

As soon it begins to import anonymous users it cancels with an error of “Invalid Email… and Validation failed: Username can’t be blank (ActiveRecord::RecordInvalid)”.

I added the error below, does anyone encountered this before or have any ideas on what I should do?

Thanks,

importing anonymous users...
Invalid email '' for ''. Using '6be92499a6f885cb271d94bffd5e667b@email.invalid'
Error on record: {:id=>"", :email=>"", :name=>"", :website=>nil}
Traceback (most recent call last):
	23: from script/import_scripts/bbpress.rb:512:in `<main>'
	22: from /home/lutechi/discourse/script/import_scripts/base.rb:49:in `perform'
	21: from script/import_scripts/bbpress.rb:31:in `execute'
	20: from script/import_scripts/bbpress.rb:153:in `import_anonymous_users'
	19: from /home/lutechi/discourse/script/import_scripts/base.rb:249:in `create_users'
	18: from /home/lutechi/discourse/script/import_scripts/base.rb:249:in `each'
	17: from /home/lutechi/discourse/script/import_scripts/base.rb:261:in `block in create_users'
	16: from /home/lutechi/discourse/script/import_scripts/base.rb:337:in `create_user'
	15: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:212:in `transaction'
	14: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:267:in `transaction'
	13: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:236:in `within_new_transaction'
	12: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
	11: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:239:in `block in within_new_transaction'
	10: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:267:in `block in transaction'
	 9: from /home/lutechi/discourse/script/import_scripts/base.rb:338:in `block in create_user'
	 8: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/suppressor.rb:48:in `save!'
	 7: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:315:in `save!'
	 6: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:385:in `with_transaction_returning_status'
	 5: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:212:in `transaction'
	 4: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:265:in `transaction'
	 3: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:387:in `block in with_transaction_returning_status'
	 2: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/transactions.rb:315:in `block in save!'
	 1: from /home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/validations.rb:52:in `save!'
/home/lutechi/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activerecord-5.2.3/lib/active_record/validations.rb:80:in `raise_validation_error': Validation failed: Username can't be blank (ActiveRecord::RecordInvalid)

Gracias por este tutorial tan útil: me funcionó, aunque tengo un par de pequeños problemas:

  1. El proceso de instalación parece haber instalado PostgreSQL 11, pero la versión de Discourse compatible es PostgreSQL 10, ¡así que eso les está dando un buen dolor de cabeza!

  2. Los usuarios importados no parecen poder iniciar sesión en Discourse con sus credenciales de WordPress. Lo intenté con mi propia cuenta de usuario, tanto con el nombre de usuario como con la dirección de correo electrónico, pero ninguno funciona. Puedo iniciar sesión en WordPress sin problemas y la cuenta de usuario está presente en Discourse, junto con los hilos del foro asociados. ¿Quizás algo cambió con las contraseñas o la autenticación?

¿Estás utilizando SSO desde WordPress?

Esto requiere el plugin de migración de contraseñas. ¿Lo has instalado?

3 Me gusta

Hola Michael,

No, esa es la primera referencia que he encontrado al complemento, así que gracias por destacarlo. Quizás me haya perdido algún paso. Gracias por compartirlo; lo revisaré más detenidamente mañana, cuando no tenga los ojos tan cansados.

Ruth

3 Me gusta

¡Hola :waving_hand:

¿También se pueden migrar las imágenes subidas por los usuarios?
El complemento para las cargas de los usuarios era GD bbPress Attachments

¡Saludos! :beers:

El script parece importar archivos adjuntos.

Debes establecer la variable de entorno BB_PRESS_ATTACHMENTS_DIR con la ruta a los archivos adjuntos.

1 me gusta

Las subidas del plugin bbPress parecen estar almacenadas en la carpeta /uploads de la instalación de WordPress. Para esto se utilizó GD bbPress Attachments. No estoy seguro de qué tipo de ruta debo colocar en la variable BB_PRESS_ATTACHMENTS_DIR. ¿Podrías ayudarme un poco? ¿Debería poner la ruta completa de la URL a las subidas, por ejemplo http://www.example.com/httpdocs/wp-content/uploads/2018/02/picture.png, o qué más?

Vi que el script de importación no terminó con éxito, ya que falló el paso import_private_messages. Los mensajes privados no estaban activados en el foro. Eliminé ese paso del script y ahora falla con el mensaje: table wp_bb_attachments doesn't exist, lo cual es cierto. Sin embargo, no puedo encontrar ninguna tabla para archivos adjuntos en la base de datos. ¿Cómo pudieron funcionar esos archivos adjuntos en primer lugar? :thinking:

Los archivos adjuntos deben estar en un directorio del servidor donde se ejecuta la importación.

Si no ves la tabla de archivos adjuntos que busca el script, es posible que hayas utilizado un método diferente para gestionar los adjuntos al que espera el script. Mi suposición es que están en una tabla distinta que aún no has encontrado o que el nombre de archivo relativo está en las propias publicaciones.

Parece que necesitas otra función para importarlos. Si tienes un presupuesto, puedo ayudarte. Redirecting… tiene información sobre las importaciones. Parece que no necesitas el servicio completo, por lo que tu costo sería menor al sugerido allí.

Dado que Discourse siempre se ejecuta en un contenedor Docker, ¿debería este directorio estar enlazado al contenedor de importación?

Correcto. Si estás ejecutando la importación desde un contenedor, necesitas colocar esas imágenes en un lugar accesible desde el contenedor y usar esa ruta.

1 me gusta

Una última pregunta. Dado que mencionaste tu servicio de importación, revisé el sitio y profundicé un poco más en mi base de datos, encontrando dónde se almacenan los archivos adjuntos. Una frase en tu página me preocupó un poco:

Por ejemplo, algunos foros pueden adjuntar archivos a una publicación sin mencionarlos en el cuerpo del mensaje; el script de importación identifica los archivos adjuntos reemplazando las referencias a ellos en el cuerpo del mensaje; cuando esto ocurre, esos archivos adjuntos sin enlace se omiten.

Descubrí que mis archivos adjuntos se almacenaban en la tabla wp_postsmeta como _wp_attached_file. Sin embargo, la publicación en sí, que tenía este archivo adjunto vinculado, no tiene ninguna mención de esto en el cuerpo del mensaje. Parece que el único enlace aquí es el post_id y su meta_id. ¿Significa esto que se trata de un “archivo adjunto sin enlace” y que será omitido?