Migrar um fórum vBulletin 4 para Discourse

Olá. Só quero compartilhar minha solução.
Quanto aos problemas com as citações. Como eu disse antes, eu estava enfrentando problemas - regexp não captura citações então:

  • nome de usuário e ID da postagem podem estar entre aspas duplas
  • citações aninhadas

Decidi fazer uma busca e substituição usando uma lógica diferente. Em vez de procurar por tags e seus conteúdos, usei uma expressão regular que procura apenas por tags:

era:
raw.gsub!(%r{\\[quote=\"?([^;]+);(\\d+)\"?\\](.+?)\\[\\/quote\\]}im) do

tornou-se:
raw.gsub!(%r{(\\[QUOTE(=\"?([^;]+);(\\d+)\"?)?\\])|(\\[\\/QUOTE\\])}im) do

e então mudei um pouco a determinação da origem de uma citação:

      if $3 && $4
        if topic_lookup = topic_lookup_from_imported_post_id(post_id)
          post_number = topic_lookup[:post_number]
          topic_id = topic_lookup[:topic_id]
          "\n[quote=\"#{new_username},post:#{post_number},topic:#{topic_id}\"]\n"
        else
          "\n[quote=\"#{new_username}\"]\n"
        end
      elsif $5
        "\n[/quote]\n"
      end

Também mudei o código do spoiler. Em vez de:

    # [spoiler=Some hidden stuff]SPOILER HERE!![/spoiler]
    raw.gsub!(%r{\\[spoiler=\"?(.+?)\"?\\](.+?)\\[/spoiler\\]}im) do
      "\n#{$1}\n[spoiler]#{$2}[/spoiler]\n"
    end

que desfoca o texto, eu o converto para a tag de detalhes:

    raw.gsub!(%r{(\\[spoiler(=\"?(.*?)\"?)?\\])|(\\[\\/spoiler\\])}im) do
      if $3
        "\n[details=#{$3}]\n"
      elsif $1
        "\n[details]\n"
      elsif $4
        "\n[/details]\n"
      end
    end

Porque acontece que no mundo vbulletin - spoiler não é o conteúdo desfocado, mas sim o conteúdo colapsado. Então eu acho que é muito mais apropriado para o script de importação vbulletin converter spoilers em detalhes em vez de spoiler desfocado.

Também notei a tag de menção. No meu caso, no vbulletin, as menções pareciam assim:
[mention=XXX]username[/mention]

A expressão regular usada no script não leva em conta que a tag pode conter o ID do usuário.

    # [MENTION]<username>[/MENTION]
    raw.gsub!(%r{\\[mention\\](.+?)\\[/mention\\]}i) do
      new_username = get_username_for_old_username($1)
      "@#{new_username}"
    end

Eu corrigi isso do meu jeito também:

    # [MENTION]<username>[/MENTION]
    raw.gsub!(%r{\\[mention(=\\d+)?\\](.+?)\\[/mention\\]}i) do
      new_username = get_username_for_old_username($2)
      "@#{new_username}"
    end
1 curtida

Isso não é verdade quando comecei a migrar meu fórum vBulletin de 24 anos rodando vB 3. Houve várias incompatibilidades e outros problemas com o script. No entanto, me esforcei muito para criar um importador para vBulletin 3 com base no script para vB4.

O script aprimorado está incluído no Discourse, ele é chamado de vbulletin3.rb. O uso do script de importação vB3 é o mesmo descrito neste tutorial. Basta executar bundle exec ruby script/import_scripts/vbulletin3.rb em vez disso.

O vBulletin3 tem algumas mudanças/melhorias significativas:

  1. As permissões do fórum são copiadas
  2. Os grupos de moderadores do fórum são criados
  3. Os grupos de usuários que podem ser ingressados são criados com a configuração adequada
  4. Aninhamento de fóruns importado em até 3 níveis de profundidade (máximo do Discourse)
  5. Permalinks são registrados para todos os tópicos e postagens, evitando quebras de link
  6. Algumas configurações básicas do fórum são copiadas (por exemplo, título, e-mail de notificação, nome da empresa)
  7. Enquetes são importadas
  8. Grandes melhorias na conversão de bbcode para markdown
  9. Links profundos de URL para tópicos, postagens e anexos são convertidos em referências do Discourse, isso requer a definição da variável de ambiente FORUM_URL para forum.hostname/path (sem protocolo).

Em vez de tentar converter mensagens privadas do vBulletin para mensagens privadas do Discourse, os usuários receberão uma mensagem privada do sistema contendo um arquivo com as mensagens privadas que eles tinham. A construção de PMs do vBulletin não é realmente compatível com o Discourse. Tentar convertê-la também exporia alguma privacidade dependendo de como as pessoas usavam PMs no vBulletin.

Como provavelmente também é o caso com outros importadores, pode levar bastante tempo para converter. O script de conversão levou 5,5 horas na minha estação de trabalho para 7 mil usuários, 16 mil tópicos, 415 mil postagens. Não tenho ideia de quanto tempo levou para o pós-processamento das postagens, deixei isso rodando durante a noite. Do início ao fim, o fórum ficou inativo por 30 horas. No final, estou feliz com o resultado.

2 curtidas

Isso sim que é uma lembrança :slight_smile:

Seu fórum está muito bonito. Gostei das cores alternadas nas linhas dos tópicos.

Parece que tanto este tópico quanto o importador estão desatualizados neste momento. Corrigi alguns problemas com a ajuda deste tópico, mas agora estou preso no seguinte passo de importação do usuário, alguém sabe como corrigir?

in at’: can’t convert NilClass into an exact number (TypeError)`

Ou a consulta está incorreta ou de alguma forma a tabela está faltando um valor

É bastante bizarro responder a isso tantos anos depois, mas estou fazendo uma importação VB agora com o importador em massa e um monte de imagens estavam faltando e o motivo é que eles moveram o nome do arquivo de anexo para um campo diferente.

 SELECT a.filedataid attachment_id, a.userid user_id, a.filename filename
             FROM attachment a
            WHERE a.attachmentid = 383075;

o arquivo NUMBER.attach agora é o campo filedataid, não o campo attachment_id. Portanto, essa consulta precisa ser atualizada no script.

Fui solicitado a migrar um fórum vbulletin 4.25 para discourse…. Ler este tópico me dá sentimentos mistos… parece que é possível, mas potencialmente uma dor de cabeça e um dreno de tempo enormes (ambos que eu poderia evitar no momento)….\n\nexiste um script atualizado para vbulletin 4.25 em algum lugar? Só consigo ver 3 e 5 na página oficial?

Bem, existem scripts vbulletin e vbulletin5 no diretório bulk imports que têm apenas alguns meses. Executar essas importações em massa é bem complicado e não está bem documentado.

Já fiz mais de 100 importações e tenho quase certeza de que nunca fiz uma que não exigisse ajustes no script por um motivo ou outro.

Escrevi vários scripts de importação antes mesmo de aprender Ruby (Mas um professor em meados dos anos 1980 me garantiu que, depois de sua aula de Linguagens de Programação, eu poderia dizer que conhecia qualquer linguagem se tivesse um fim de semana e um livro; ele estava, na maioria, certo.)

Mas sim, é provável que seja pelo menos tão trabalhoso e demorado quanto você imagina.

Suspeito que o script do vbulletin fará um bom trabalho; provavelmente não recomendaria o script de importação em massa, a menos que você tenha mais de um milhão de posts + usuários.

1 curtida

Obrigado por isso :slight_smile:

Acho que preciso decidir o que vou fazer no meu fim de semana :smiley:

1 curtida

Eu realmente apreciaria alguma ajuda com isso :face_with_spiral_eyes:

Eu li o tópico e segui alguns passos que vi aqui, mas estou travado.

  1. Eu faço SSH no meu VPS
  2. Entro na imagem do Docker
  3. Instalo o mariadb-server
  4. Tento executar o comando mysql para criar um banco de dados, mas recebo ‘can’t connect to local server through socket’

As instruções aqui são de alguns anos atrás - eu vi algumas pessoas terem o mesmo erro, mas não vejo nenhuma resolução para isso.

Alguém fez esse processo recentemente e pode me indicar a direção certa - não acho que esteja faltando um guia passo a passo em algum lugar, certo?

editar: só para acrescentar, eu tentei todo tipo de artimanhas e acabei instalando uma imagem docker do mariadb no host local (não docker) e depois expondo a porta - agora consigo me conectar ao banco de dados a partir da imagem docker… mas executar o script dá: Gemfile: Variável local ou método ‘mysql2’ indefinido. Eu tentei instalar o gemfile, mas falha… e antes que eu resolva mais problemas, tenho a sensação de que estou usando informações desatualizadas e pacotes potencialmente antigos… estou muito confuso e poderia usar alguma orientação!

Qualquer ajuda é bem-vinda!

…persisti e finalmente consegui executar o script! No entanto, após iniciar a execução, ele falha com:

"root@vps-xxxxxxxx-app:/var/www/discourse/script/import_scripts# bundle exec ruby vbulletin.rb
/var/www/discourse/config/initializers/013-excon_defaults.rb:4:in `<main>': can't modify frozen Hash: {:chunk_size=>1048576,                                                             :ciphers=>"ECDHE-ECDSA- [................]"

…e acho que cheguei ao meu limite de capacidade de solução de problemas.

Não sei se iniciá-lo a partir de /var/www/discourse faz diferença, mas eu sempre faço. Aqui está o que é recomendado no OP.

Não reconheço esse erro.

1 curtida

No momento em que desisti ontem à noite, após horas de “pesquisa”, mexi em tantas coisas fora da minha zona de conforto que fiquei preocupado em estar causando mais mal do que bem. Eu também estava ansioso para saber se alguém tinha feito isso recentemente e havia algum passo mágico que eu estava perdendo, em vez de descer em espirais por buracos de coelho recorrentes :winking_face_with_tongue:

É possível que haja algum problema novo. Fiz uma importação de mbox outro dia, e imagino que ela chame o mesmo código que lhe deu o erro.

Ah. Eu fiz isso em um contêiner e estas instruções são para um ambiente de desenvolvimento. Você configurou um ambiente de desenvolvimento? Você conseguiu fazer funcionar? Isso é complicado em uma VPN.

Vou formatar e tentar novamente amanhã, enxaqueca esta noite.

Avisarei como correu :slightly_smiling_face:

1 curtida

Você configurou um ambiente de desenvolvimento? Esse foi o seu primeiro passo?

Tentei fazer isso através do VPS do host e improvisando através do contêiner. Quando terminei, não tinha certeza do que fiz e onde. Provavelmente é uma questão de habilidade… Começarei de novo amanhã.

Se você estiver fazendo isso em uma VM, fazer isso em um contêiner provavelmente é mais fácil. Eu daria uma olhada em outros exemplos de importação (eles incluirão o modelo mysql).

Você entrará no contêiner, talvez edite o Gemfile e execute o bundle install.

Usar um contêiner para mysql ou mariadb provavelmente faz sentido. (mas então você precisará garantir que os contêineres possam se ver)

1 curtida

Tenho novidades animadoras…

Consegui fazer o script rodar (vou fazer um guia assim que terminar), ele importou os grupos de usuários, mas travou na importação de usuários, acho que tem a ver com a variável de fuso horário?

importing users
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/tzinfo-2.0.6/lib/tzinfo/timestamp.rb:138:in `for': Integer values are not supported (ArgumentError)

            raise ArgumentError, "#{value.class} values are not supported" unless is_time_like?(value)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/tzinfo-2.0.6/lib/tzinfo/timezone.rb:575:in `utc_to_local'
        from script/import_scripts/vbulletin.rb:1019:in `parse_timestamp'
        from script/import_scripts/vbulletin.rb:166:in `block (2 levels) in import_users'
        from /var/www/discourse/script/import_scripts/base.rb:267:in `block in create_users'
        from /var/www/discourse/script/import_scripts/base.rb:266:in `each'
        from /var/www/discourse/script/import_scripts/base.rb:266:in `create_users'
        from script/import_scripts/vbulletin.rb:148:in `block in import_users'
        from /var/www/discourse/script/import_scripts/base.rb:951:in `block in batches'
        from <internal:kernel>:187:in `loop'
        from /var/www/discourse/script/import_scripts/base.rb:950:in `batches'
        from script/import_scripts/vbulletin.rb:126:in `import_users'
        from script/import_scripts/vbulletin.rb:82:in `execute'
        from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
        from /var/www/discourse/script/import_scripts/vbulletin.rb:1027:in `<main>'

O padrão no script é “America/Los Angeles” - o fórum vBulletin está configurado para (GMT) Europa Ocidental, Londres, Lisboa, Casablanca) e a instância do discourse na qual estou importando tem duas entradas: America/Los Angeles e Europe/Paris.

Você sabe qual devo escolher?

Não importa muito qual você escolher.

Acho que pode ser que a data não esteja armazenada da maneira que o script espera.

1 curtida