Migrar un foro vBulletin 4 a Discourse

Sí, se convierten. ¡Te enviaré un correo electrónico mañana!

3 Me gusta

Debes alcanzar el nivel de confianza 1 para desbloquear los mensajes privados, y aún no has pasado suficiente tiempo leyendo temas aquí para lograrlo.

4 Me gusta

Hola, estoy en un contenedor Docker (DigitalOcean) y estoy intentando importar miBB (sé que este tutorial es para Vbulletin, pero lo del Gemfile es similar). Estoy atascado en bundle install:

Hola,

Intentamos importar vBulletin v3.8 a Discourse. Este script funciona bien con una base de datos de 300 MB, alrededor de 40 000 usuarios y 60 000 publicaciones. Sin embargo, al final del proceso de importación nos enfrentamos a un problema con la codificación de caracteres.

  • Nuestra instalación de vBulletin 3.8 está codificada con el conjunto de caracteres latin1.
  • Al ejecutar el script de importación, MySQL 5.6 en el contenedor de Docker de Discourse también está configurado con el conjunto de caracteres UTF-8.
  • El script de importación fuerza la conversión de los datos a UTF-8 durante el proceso.

Por lo tanto, al finalizar la importación, el foro de Discourse muestra los datos con errores de codificación UTF-8, como se ve en la siguiente imagen:

  1. Antes de la importación, vB 3.8

  2. Después de la importación a Discourse

Hemos intentado lo siguiente:

  • Convertir el conjunto de caracteres de vB 3.8 a UTF-8 antes de ejecutar el script de importación.
  • Probar esta base de datos de vB 3.8 en un nuevo servidor MySQL, donde el texto se muestra correctamente sin errores de codificación.

¿Podrían darnos algún consejo en este caso?

Agradecemos cualquier apoyo al respecto (y también disculpen mi inglés si les resulta difícil de entender).

1 me gusta

Aquí tienes un fragmento de cómo solucioné un problema similar:

    ### Codificación WIN1252
    win_encoded = ''
    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 falló para \n\n#{raw}\n\n"
      win_encoded = ''
    end
    raw = win_encoded
5 Me gusta

Me has salvado la vida.
Para la solución sencilla, probé el script de conversión en el post Migrate a phpBB3 forum to Discourse - #540 by gerhard, ayúdame a solucionar rápidamente el problema de codificación de caracteres de mi base de datos, y ahora funciona como un encanto.
Muchas gracias por el consejo.

3 Me gusta

¿Alguien ha migrado usando el importador de vbulletin5? Es posible que lo use en el futuro, me gustaría saber si ya se ha utilizado sin problemas.

2 Me gusta

Acabo de realizar una importación de vBulletin5 y agregué algunas funciones (enlaces permanentes, cierto formato y quizás otras cosas que no recuerdo). Planeo enviar una PR, pero aún no lo he hecho.

3 Me gusta

Tengo un volcado de base de datos de vb5 que contiene adjuntos. ¿Puedo importarlos en Discourse o necesito tener todos los adjuntos como archivos?

También estoy confundido con esto. ¿Dónde exactamente debo copiar los archivos de adjuntos en la carpeta de Discourse? :thinking:

2 Me gusta

Hola de nuevo,
Por lo que entiendo, los archivos adjuntos de la base de datos deberían funcionar, ya que parecen gestionarse de la misma manera que los avatares, que también están en la base de datos.

Mi importación va bien, pero he encontrado un error al 91% de las publicaciones importadas :weary_face:

importando publicaciones...
  1425149 / 1564573 ( 91.1%)  [1040 elementos/min]  Traceback (última llamada en orden):
        14: from script/import_scripts/vbulletin5.rb:726:in `<main>'
        13: from /home/canapin/discourse/script/import_scripts/base.rb:47:in `perform'
        12: from script/import_scripts/vbulletin5.rb:49:in `execute'
        11: from script/import_scripts/vbulletin5.rb:300:in `import_posts'
        10: from /home/canapin/discourse/script/import_scripts/base.rb:862:in `batches'
         9: from /home/canapin/discourse/script/import_scripts/base.rb:862:in `loop'
         8: from /home/canapin/discourse/script/import_scripts/base.rb:863:in `block in batches'
         7: from script/import_scripts/vbulletin5.rb:320:in `block in import_posts'
         6: from /home/canapin/discourse/script/import_scripts/base.rb:508:in `create_posts'
         5: from /usr/local/rvm/gems/ruby-2.6.5/gems/rack-mini-profiler-2.0.4/lib/patches/db/mysql2.rb:8:in `each'
         4: from /usr/local/rvm/gems/ruby-2.6.5/gems/rack-mini-profiler-2.0.4/lib/patches/db/mysql2.rb:8:in `each'
         3: from /home/canapin/discourse/script/import_scripts/base.rb:509:in `block in create_posts'
         2: from script/import_scripts/vbulletin5.rb:321:in `block (2 levels) in import_posts'
         1: from script/import_scripts/vbulletin5.rb:450:in `preprocess_post_raw'
script/import_scripts/vbulletin5.rb:450:in `gsub': secuencia de bytes inválida en UTF-8 (ArgumentError)

¿Cómo puedo identificar correctamente la publicación para ver cómo es su contenido en la base de datos de vbulletin?

1 me gusta

Alguien sugirió formas de usar rescue para resolver esos problemas, así que podrías volver y encontrar eso (no recuerdo si fue en este tema o en otro). Podrías agregar un puts en el rescue para imprimir el id y/o el texto que causó el problema.

Tienes un problema de codificación.

Yo usé esto en una importación similar (creo que lo pondrías en preprocess_post_raw)

    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 falló para \n\n#{raw}\n\n"
      win_encoded = ''
    end
3 Me gusta

Hola,
Modifiqué el importador y agregué tu script de la siguiente manera:

  def preprocess_post_raw(raw)
    return "" if raw.blank?
    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 falló para \n\n#{raw}\n\n"
      win_encoded = ''
    end
    # decodificar entidades HTML
    raw = @htmlentities.decode(raw)

    # corregir espacios en blanco
    raw = raw.gsub(/(\\r)?\\n/, "\n")
      .gsub("\\t", "\t")

La secuencia de bytes inválida en UTF-8 ocurre en esta parte: raw = raw.gsub(/(\\r)?\\n/, "\n") .gsub("\\t", "\t").

Luego reinicié el importador. Aunque omite los datos que ya se estaban importando, tardó unas 6 horas en llegar al post que genera el error, y no agregó la información esperada para ver el contenido del post. :confounded_face: ¿Alguna idea de por qué?

edición:

Probablemente este sea el contenido crudo del post que provoca el error:

Me pregunto si Billy está disfrutando del desfile.

Qwertyuiopasdfghjklzxcvbnm&#55356;&#57174;

Intentaré modificar el script del importador para que omita (de verdad) los 1.4 millones de posts anteriores. ¡Dadme suerte. :crossed_fingers:

2 Me gusta

He modificado muchos otros importadores para incluir una configuración import_after que permite importar solo datos recientes. Puedes consultar algunos de ellos para ver cómo lo hice.

2 Me gusta

Hola,
¡He logrado importar casi todas mis publicaciones! Corregí a mano unas cuantas decenas y reinicié la importación cada vez que aparecía un nuevo error de UTF-8… :sweat_smile:

Ahora necesito importar los archivos adjuntos (que están almacenados en la base de datos de VBulletin), pero no funciona:
Cuando inicia el proceso, mi consumo de RAM aumenta mucho en unos 10 o 20 segundos y ocurre este error:

importing attachments...
Failed to create upload: Cannot allocate memory - grep
Fail

Mi RAM:

Uso una versión de desarrollo de Discourse en un subsistema de Ubuntu 18 sobre Windows 10 y tengo 16 GB de RAM.

Los archivos adjuntos ocupan 7 GB de los 13 GB de la base de datos de vBulletin.
Tenga en cuenta que uso el importador vbulletin5.

El problema proviene de esta consulta:

    SELECT n.parentid nodeid, a.filename, fd.userid, LENGTH(fd.filedata) AS dbsize, filedata, fd.filedataid
      FROM #{DB_PREFIX}attach a
      LEFT JOIN #{DB_PREFIX}filedata fd ON fd.filedataid = a.filedataid
      LEFT JOIN #{DB_PREFIX}node n on n.nodeid = a.nodeid

Si ejecuto esta consulta en MySQL, mi RAM restante se llena en cuestión de segundos.


(editando mi publicación para eliminar información y preguntas innecesarias, ya que estoy resolviendo el problema y proporcionando una solución alternativa)

Solución alternativa:

Añadí un límite y un desplazamiento (offset) a la consulta SQL del importador. Importé los archivos adjuntos seleccionando 20000 de ellos en cada ejecución:

    uploads = mysql_query <<-SQL
    SELECT n.parentid nodeid, a.filename, fd.userid, LENGTH(fd.filedata) AS dbsize, filedata, fd.filedataid
      FROM #{DB_PREFIX}attach a
      LEFT JOIN #{DB_PREFIX}filedata fd ON fd.filedataid = a.filedataid
      LEFT JOIN #{DB_PREFIX}node n on n.nodeid = a.nodeid
      LIMIT 20000 OFFSET 0
    SQL

También añadí un exit al final del bucle uploads.each do |upload| para evitar que el script de importación continúe ejecutando otras tareas después de importar mis 20000 archivos.

Cuando mis 10000 archivos se importaron, edité el script (gracias a nano +353 ./scripts/import_scripts/vbulletin5.rb para abrir el archivo en la línea correcta) para aumentar el OFFSET de la consulta SQL en 10000 y reinicié el importador… Repitiendo esto para mis 65000 archivos adjuntos.

Durante la importación de archivos adjuntos, me encontré con varios errores y advertencias, entre ellos:

  • W, [2020-08-20T12:05:37.402860 #31042] WARN -- : Bad date/time value "0000:00:00 00:00:00": mon out of range
  • Post for 490451 not found (supongo que son archivos adjuntos antiguos huérfanos)
  • Algunos errores de datos EXIF, parece
  • Fail Este me confundió y detuvo el script de importación. Revisé el primer “Fail” que obtuve y el archivo adjunto del foro estaba algo roto (sin nombre de archivo), así que comenté la instrucción exit para permitir que el importador continuara su trabajo cuando “falla”, con la esperanza de que no rompiera nada.
       puts "Fail"
       #exit

También tuve un error más molesto que interrumpió la importación:

1: from /usr/local/rvm/gems/ruby-2.6.5/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:53:in `save!'
/usr/local/rvm/gems/ruby-2.6.5/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:80:in `raise_validation_error':
Validation failed: Body is limited to 32000 characters; you entered 32323. (ActiveRecord::RecordInvalid)

Afortunadamente, fue un error raro y simplemente omití este archivo adjunto hasta que me encontré con el siguiente error idéntico. Ocurrió quizás una docena de veces en un total de 65000 archivos adjuntos. Simplemente reinicié el script de importación con un desplazamiento de consulta SQL diferente.

1 me gusta

Hola,
Noté que el campo personalizado import_pass estaba ausente en unos 400 de mis 27000 usuarios restantes (limpié 154000 usuarios inactivos).

¿Alguna idea de por qué?

El foro fue migrado de phpBB a vBulletin en mayo. ¿Podría tener algo que ver con eso?

No voy a intentar “arreglar” esto e importar las contraseñas para esos 400 usuarios (a menos que haya una forma sencilla de hacerlo…), y no es un gran problema, así que solo estoy más curioso que otra cosa.

1 me gusta

Hola a todos,

Las imágenes importadas tienen una relación de aspecto (ancho/altura) incorrecta a menos que vuelva a hornear (rebake) las publicaciones. Me gustaría encontrar una forma de obtener la relación correcta (por ejemplo, durante la importación) sin necesidad de volver a hornear.

Descripción más detallada del problema:

Por lo que entiendo, las publicaciones importadas no se “hornean” cuando Discourse crea la publicación correspondiente (aunque el campo cooked se genera de alguna manera), por eso la importación de publicaciones es mucho más rápida que hornear publicaciones existentes de Discourse.

Mi problema es que las imágenes importadas tienen una relación de aspecto (ancho/altura) incorrecta.

Ejemplo del texto crudo de Discourse relacionado con una imagen importada:

![SH-MUniFrame.JPG|600x800](upload://6Li1nnjbA8zDz6YJ3FqeYHV5zXK.jpeg)

El contenido del campo “cooked”:
<img src="https://d11a6trkgmumsb.cloudfront.net/original/3X/0/3/0379f53ed8221730ccb31807238e9c46e9fe1d37.jpeg" alt="SH-MUniFrame.JPG" data-base62-sha1="6Li1nnjbA8zDz6YJ3FqeYHV5zXK" width="517" height="500" class="d-lazyload">

Así es como aparece la imagen en: la publicación


Aquí está la imagen original: https://d11a6trkgmumsb.cloudfront.net/original/3X/f/7/f73a0ae8594219dd5a1620e59b3c17f9b02b1583.jpeg

El tamaño original de la imagen en la base de datos de vBulletin es:

select width, height from filedata where filedataid = 76237
+-------+--------+
| width | height |
+-------+--------+
|   600 |    800 |
+-------+--------+

Mi entendimiento es que el atributo de altura está limitado por la configuración de Discourse, que establece una altura máxima de 500 px, de ahí el mismo valor en el atributo height de la etiqueta <img>. El ancho de la etiqueta <img> se modifica ligeramente de 600 a 517, aunque no logro entender cómo ni por qué.

El problema es el mismo para imágenes más antiguas que tienen 0 tanto en los campos de ancho como de altura de los archivos adjuntos de vBulletin. Estas también presentan el problema incorrecto de altura/ancho. No sé si estos valores se utilizan realmente durante la importación.

El problema se resuelve volviendo a hornear (reconstruir el HTML) la publicación. La imagen se redimensionará correctamente y se añadirá el visor de imágenes. Pero tengo 1,6 millones de publicaciones y preferiría evitar volver a hornear todas.

Una solución rápida sería usar este CSS en mi Discourse:

.cooked img:not(.emoji) {
    height: auto;
    width: auto;
}

Pero esto implica que nadie podrá elegir un tamaño arbitrario al subir una imagen, y podría haber efectos colaterales de los que no soy consciente.

¿Alguna idea sobre cómo lograr una relación de aspecto correcta en las imágenes de los archivos adjuntos importados?

Sospecho que es porque no les permitiste cocinar después de la importación. No puedo imaginar una forma de resolver el problema sin volver a hornear las publicaciones. ¿Quizás quieras volver a hornear solo las publicaciones que están rotas en lugar de todas?

1 me gusta

¿Se supone que deben cocinarse automáticamente con el tiempo después de la importación? ¿Empezando desde el último o desde el primer post creado?

Aun así, no es un gran problema. Si no se cocinan automáticamente, probablemente iniciaré una recocción de todos los posts y tendré paciencia, aunque admito que leí este post hace unos días y me asustó un poco: My journey into a massive posts rebake job. También tengo preguntas sobre eso, pero las haré en el tema correspondiente. :blush:

Hmm, sí, parece que es mi código. Lo siento por eso. :confused:

Esto debería seguir este patrón:

   batches(BATCH_SIZE) do |offset|
       (código SQL)
        LIMIT #{BATCH_SIZE}
        OFFSET #{offset}
       (otro código)
    end
1 me gusta

Simplemente aumenta la configuración del sitio longitud máxima de publicación antes de la importación.

2 Me gusta