Migrar um fórum SMF2 para Discourse

Tentamos e estamos enfrentando estes problemas: importou todas as postagens, mas os títulos dos tópicos não aparecem e as imagens externas não são renderizadas. O fórum SMF2 atual é: https://forum.mundofotografico.com.br estamos tentando migrar para o Discourse aqui: https://discourse.fotografos.online - Todos os tópicos e descrições adequadas não vieram, as imagens não estão carregando… por favor, ajude! @marcozambi @miligraf @FireAllianceNX @pfaffman

Estou apenas começando o processo de migração do SMF e, no momento, estou importando posts para uma instância de teste a uma taxa de cerca de 1000/hora, então tudo está indo bem até agora, exceto pelo script de desempenho do MySQL, onde o MySQL não gostou do comando ‘ALTER USER’ por algum motivo. Eu manualmente executei um ‘CREATE USER’ e tudo ficou bem depois disso.

Li o comentário sobre usuários excluídos, mas não consigo criar facilmente novos usuários/e-mails falsos para cobrir todos os meus usuários excluídos (meu fórum está em execução há mais de 20 anos e provavelmente tenho mais usuários excluídos do que usuários reais agora). Suspeito que tenho de 4 a 5000 usuários excluídos. Nem todos terão postado, mas muitos terão postado, então provavelmente tenho muitas centenas de usuários ‘ausentes’.

Os posts estão sendo importados como pertencentes ao ‘system’, o que não é realmente ideal. Eu me perguntei se o seguinte funcionaria.

  1. Antes de importar, crie um usuário fictício, por exemplo, ‘Usuário Excluído’.
  2. Descubra o número do usuário para ‘Usuário Excluído’
  3. Modifique a linha “user_id: user_id_from_imported_user_id(message[:id_member]) || -1,” em smf2.rb e substitua o ‘-1’ pelo número do usuário de ‘Usuário Excluído’ (acho que o usuário do sistema é -1?)

Isso funcionaria? Além disso, existem outros lugares em smf2.rb onde eu precisaria fazer uma alteração semelhante?

Olá, por “excluídos” você quer dizer que eles foram realmente excluídos do banco de dados do SMF, ou eles ainda estão no banco de dados com nome de usuário e e-mail e marcados como suspensos? Como as postagens desses usuários “excluídos” são exibidas atualmente no SMF?

Estou no meio de uma enorme migração do Drupal para o Discourse, também de um fórum de longa data com toneladas de usuários suspensos. Eu definitivamente queria manter esses mesmos nomes de usuário suspensos e seus endereços de e-mail associados no Discourse, então tive que adicionar essa função ao script de importação do Drupal para o Discourse. Basicamente, o script importa todos os usuários como usuários ativos normais, e se eles tivessem alguma postagem publicamente visível, elas também seriam importadas como no fórum original. Então, no final do processo, adicionei uma função que peguei de outro script de importação para percorrer o banco de dados do Drupal e, se o usuário estivesse marcado como suspenso, suspender também a conta do Discourse. Você pode ver o código para isso no meu histórico de postagens aqui.

1 curtida

Olá. Os usuários são realmente excluídos, ou seja, não há mais um registro deles na tabela smf_member. O SMF não tem uma função para suspender usuários. Você pode banir usuários, mas isso não parece certo para uma conta onde o usuário faleceu ou perdeu o interesse no hobby/fórum. Também não é realmente correto da perspectiva de proteção de dados.

As postagens do SMF têm dois campos armazenados para cada registro… o número do membro do usuário, que é definido como zero para usuários excluídos, e o nome do remetente, que contém o nome de usuário do remetente. Assim, você pode ver qual usuário postou a mensagem, mas não há mais detalhes (e-mail, nome completo, etc.) disponíveis para o usuário. Suas postagens têm um marcador de ‘Convidado’ quando exibidas.

Acho que poderia criar uma nova conta de usuário para cada usuário que postou uma mensagem com ID de membro zero e atribuir um endereço de e-mail fictício para a conta, depois marcar o usuário como suspenso. Poderia marcar contas como suspensas com base no formato do endereço de e-mail fictício se usasse algo único, mas identificável. Isso parece um pouco estranho em alguns casos… criar contas para pessoas que sei que faleceram há 10-15 anos!

Tenho tempo para pensar sobre isso… a migração funcionou parcialmente, mas agora preciso descobrir por que os anexos não foram anexados, os links dentro do fórum não foram modificados e por que as senhas dos usuários migrados não funcionam. Pode haver outros problemas também, mas vou trabalhar para corrigir esses problemas primeiro e depois ver o que mais aparece.

Você quer dizer Postgres? Não tenho certeza do que se trata.

O que eu faria é, se o ID do usuário for 0, usar o nome de usuário para o ID. Então, se find_username_by_import_id não conseguir encontrar o usuário, crie o usuário, definindo o endereço de e-mail para fake_email (é uma função em base.rb que gera um endereço de e-mail falso) e o nome de usuário com o nome de usuário que você tem. Então, se você for ambicioso, poderá, no final do script, suspender todos os usuários que têm @email.invalid em seus endereços de e-mail. Eles não estarão ativos, então não acho que faria muita diferença se você não os suspendesse.

Outra maneira seria fazer uma consulta que de alguma forma gerasse uma lista de todos os usuários excluídos e, em seguida, criá-los antes de começar a postar, mas isso parece mais difícil.

Se você quiser criar um usuário deleted user e ter todas essas postagens pertencentes a esse usuário em vez de system, você pode fazer isso e apenas substituir o -1 pelo número do usuário de deleted user. Você pode criá-lo como um usuário regular ou fazer algo sofisticado e dar a ele um ID de usuário de -2 ou algo assim.

Em alguns sistemas, isso ocorre porque às vezes os anexos estão no corpo da postagem e, em outros, o registro do anexo está no banco de dados.

Você instalou o plugin Suporte a hashes de senhas migrados depois de executar a importação (ele pode interferir na execução de importações em pelo menos algumas circunstâncias). O SMF2 faz hash de senhas da mesma forma que o smf faz?

Desculpe, nome errado para o script. É o script MySQL referido na primeira postagem

– file: ~/smf2/script_for_mysql_tuning.sql
ALTER USER ‘user’@‘%’ IDENTIFIED WITH mysql_native_password BY ‘pass’;

Obrigado pelas sugestões sobre usuários e, particularmente, fake_email. Minha primeira tarefa é aprender o suficiente de Ruby para poder fazer alterações no script de importação!

Anexos do SMF2 são registros no banco de dados. Tendo investigado um pouco mais, parece que alguns foram importados, mas apenas algumas centenas de dezenas de milhares. Continuarei investigando para ver se consigo descobrir o porquê.

Ahhh, é provavelmente isso que está faltando! Tenho quase certeza de que o SMF2 usa o mesmo hashing (MD5 com salt, se bem me lembro) que o SMF1, então o plugin provavelmente corrigirá o problema. Preciso fazer mais algumas importações antes de me preocupar muito com os usuários fazendo login.

Outra pergunta me vem à mente. Existe uma maneira de redefinir o sistema para me permitir fazer outra importação. Eu deveria ter feito um backup antes de começar, mas esqueci :anguished:

Ah. Você quer dizer apenas configurar o mysql. Entendi.

Se você conhece outras linguagens, provavelmente pode se virar.
Eu escrevi vários importadores antes de fazer qualquer coisa como aprender Ruby. :slight_smile:

Aqui está uma maneira de remover e criar um novo banco de dados Discourse.

sv stop unicorn;DISABLE_DATABASE_ENVIRONMENT_CHECK=1 IMPORT=1 rake db:drop db:create db:migrate; sv start unicorn

Se você se lembrar de fazer um backup, isso pode ser um pouco mais rápido. Talvez.

Outro truque, depois que você tiver os usuários configurados, é parar o script após a importação dos usuários e fazer um backup nesse momento. Isso permitirá que você depure a importação de posts sem ter que importar todos os usuários novamente.

Eu conheço alguns. Escrevi meu primeiro programa em 1976 em código de máquina binário em um Intel 4004. Estou começando a entender o smf2.rb com um pouco de DuckDuckGo para entender algumas das estruturas de código que são novas para mim.

Obrigado pelo método de drop/create de banco de dados. Hora de recomeçar e ver se consigo fazer algumas alterações incrementais no importador para meus dados.

1 curtida

Consegui modificar o importador para criar contas fictícias com um endereço de e-mail falso para usuários excluídos e as contas fictícias possuem suas postagens corretas, então esse é um bom começo.

Estou tentando entender os anexos a seguir, pois não vejo nenhum nas postagens que importei até agora (e deveria haver alguns).

Se eu criar uma mensagem normalmente pela página da web do Discourse, obtenho um registro na tabela posts (id=4346), dois registros na tabela uploads (ids=403 e 404), quatro registros em upload_references (403/Draft/4, 403/Post/4346, 404/Draft/4, 404/Post/4346). Também vejo 403 no campo image_upload_id para a postagem 4346 e HTML referindo-se aos dois uploads no campo posts/cooked.

Para postagens importadas, obtenho um registro na tabela posts para cada mensagem SMF importada e um registro na tabela uploads para cada anexo associado a uma mensagem SMF importada. Os registros da tabela uploads referem-se a arquivos em disco que contêm as imagens corretas, então essa parte está funcionando bem. No entanto, não obtenho nenhum registro upload_references para as imagens carregadas ou nenhum dos IDs de upload no campo image_upload_id na tabela posts.

Presumo que preciso tentar criar os registros upload_references e popular os campos posts-image_upload_id e cooked, mas queria verificar primeiro se não há outra maneira de associar uploads a postagens que está sendo usada (ou tentando ser usada) pelo importador?

Parece que você precisa adicionar uma referência ao host/upload em raw. Existe alguma função que irá gerar um link para você. Não me lembro qual é o nome. Acho que está no modelo de uploads, mas pode ser mais fácil de encontrar em algum outro script de importação se você não sabe o que é um modelo.

Estava progredindo na adaptação do script de importação para atender às peculiaridades do meu fórum, mas parei abruptamente há alguns dias. Após a última atualização do Discourse beta, não consigo mais construir o contêiner de importação. Recebo…

> FAILED
> --------------------
> Pups::ExecError: cd /var/www/discourse & apt-get update & DEBIAN_FRONTEND=noninteractive apt-get install -y libmariadb-dev falhou com retorno #<Process::Status: pid 439 exit 100>
> Localização da falha: /usr/local/lib/ruby/gems/3.1.0/gems/pups-1.1.1/lib/pups/exec_command.rb:117:in `spawn'
> exec falhou com os parâmetros {"cd"=>"$home", "cmd"=>["echo \"gem 'mysql2'\" >> Gemfile", "apt-get update & DEBIAN_FRONTEND=noninteractive apt-get install -y libmariadb-dev", "su discourse -c 'bundle config unset deployment'", "su discourse -c 'bundle install --no-deployment --path vendor/bundle --jobs 4 --without test development'"]}
> bootstrap falhou com o código de saída 100
> ** FALHA AO INICIAR ** por favor, role para cima e procure por mensagens de erro anteriores, pode haver mais de uma.

Vi as postagens sobre o vencimento da chave do yarn e corrigi isso. Isso estava impedindo a instalação do pacote libmariadb-dev, mas fiz uma instalação manual do pacote que funcionou corretamente. A reconstrução da importação ainda não funciona com o template de importação mysql ativado, mesmo após a instalação manual do pacote MariaDB.

Construí um novo servidor e comecei com uma instalação limpa do Discourse apenas para evitar quaisquer problemas potenciais com o servidor/instalação anterior. No entanto, o novo servidor apresenta o mesmo erro do antigo.

Não tenho mais ideias do que tentar, então agradecerei quaisquer sugestões!

Veja Apt-get update fails inside container yarn repo not signed - #5 by pfaffman. Você precisará editar o template do mysql.

1 curtida

Obrigado por me indicar a direção certa. Agora vejo o que fiz de errado!

1 curtida

Estamos começando com a migração de teste de um fórum SMF 2 (v2.0.15 para ser exato) e um dos primeiros problemas que surgiram é um problema quando as categorias têm um ampersand em seu nome:

Títulos de tópicos com o mesmo parecem estar bem:
image

Até agora, parece que o ampersand é o único caractere problemático e, por exemplo, os umlauts alemães estão bem:

Provavelmente também estamos sendo afetados por problemas relatados aqui no tópico (usuários excluídos, anexos, links dentro do fórum), mas a importação ainda está em andamento, então atualizarei assim que ela for concluída.

A esse respeito, pergunto-me se a velocidade de importação é realmente suposta ser tão lenta. Atualmente, estamos importando a 1750 itens/min (inicialmente era um pouco mais perto de 2000 itens/min) em uma máquina AMD Ryzen 5 3600 com 64 GB de RAM (Hetzner, Ubuntu 22.04), o que coloca toda a migração em aproximadamente 3 dias.

Essa é uma velocidade muito boa.

Imagino que quaisquer problemas relatados ainda existam, embora um número surpreendente de coisas seja exclusivo de um fórum. Se você gostaria que algumas coisas fossem corrigidas e tem um orçamento, ficarei feliz em ajudar.

1 curtida

Obrigado! Entrarei em contato assim que as coisas ficarem mais concretas.

No momento, nós (pequena organização sem fins lucrativos focada em jogos de RPG de mesa e hobbies relacionados) estamos na fase de avaliação - há um consenso de que queremos um novo software e o Discourse, até agora, é a opção favorita. Mas teremos que coletar todas as tarefas (migração, novo tema, novos plugins/componentes de tema, se necessário) e ver se conseguimos encaixar tudo em nosso orçamento.

1 curtida

Existe um motivo especial para esta etapa?

Pelo que consigo ver na releitura cuidadosa do OP, esse arquivo smf2.rb não foi alterado/corrigido?

E se smf2.rb estiver localizado no host em (por exemplo) /var/discourse/smf2 e você configurou seu volume mount na Etapa 2 de acordo, ele já é montado dentro do guest em /shared/smf2 de qualquer maneira.

Eu não entendo a necessidade de copiá-lo como uma etapa separada. Mas entender isso pode ser a chave para descobrir por que 95% dos anexos não estão sendo encontrados corretamente pelo script…

1 curtida

Parece que você está certo sobre a (falta de necessidade) de copiá-lo. Talvez o autor o tenha alterado e suas alterações tenham sido subsequentemente incorporadas ao núcleo.

Se você está obtendo 5% e não 0% dos anexos, então parece que há algo errado com o script.

Em alguns sistemas, existem duas maneiras de anexar arquivos, uma mencionando-o no arquivo (portanto, está no texto bruto da postagem e é tratado dessa forma) e outra tendo-o anexado à postagem em alguns metadados/tabela. Minha suposição é que você tem 95% em seu banco de dados feito de uma maneira e o script faz a outra.

Mas parece que ele pode estar tentando de ambas as maneiras? Você precisará encontrar uma postagem que deva ter um anexo, olhar no banco de dados e no sistema de arquivos para ver como ele é armazenado e, em seguida, olhar o código para ver por que ele não o está obtendo.

1 curtida

Obrigado @pfaffman, isso é tranquilizador! Eu meio que pensei que esse era provavelmente o caso, mas como estou tendo tantos problemas com esta importação, tenho duvidado do meu conhecimento e habilidades em todos os níveis!

Obrigado pelas dicas, tudo é apreciado @pfaffman - esta é uma nova tentativa, muito atrasada, no mesmo fórum em que estava trabalhando no ano passado. É um trabalho voluntário, mas posso envolvê-lo novamente se você tiver tempo.

É um fórum SMF2 muito antigo que tem anexos nas duas formas:

  • \u003cid\u003e_\u003cNome_do_arquivo_SEM_CAIXA_regras_jpg\u003e_\u003c32caracteresprovavelmentehashMD50fsom4thing\u003e
  • \u003cid\u003e_\u003c40caracteresprovavelmentehashSHA10fsom4thing\u003e

Ainda estou tentando descobrir se há um padrão para as falhas.

Minha suposição (sem olhar o código!) é que uma delas é o que o script faz e a outra não (provavelmente uma é o jeito antigo, então novas postagens usam o outro método, mas ele não voltou para corrigir aquelas que usam o outro método).

Então verifique convert_message_body e os campos na tabela de anexos. Talvez eles tenham mudado de MD5 para SHA1 ou vice-versa por algum motivo.

Como eu disse, pode ser que uma versão delas tenha uma referência ao upload em vez de tê-lo vinculado na tabela, então você faria um gsub para procurar por esse padrão, e então, se correspondesse, você obteria a chave, procuraria na tabela, e então create_upload com esse arquivo. .

Espero que isso seja suficiente para você começar, mas por favor, entre em contato comigo se quiser mais ajuda do que posso dar aqui.