Mesclar dois sites Discourse em um só

Se você tem dois sites Discourse que gostaria que fossem um só, este guia é para você.

Existe uma ferramenta chamada discourse_merger que pode pegar um site Discourse e mesclá-lo em outro.

Pré-requisitos

Esta não é uma tarefa fácil e deve ser tratada como qualquer outra migração para o Discourse. Você não executará o discourse_merger em um site de produção ativo. Você realizará a mesclagem em outro ambiente onde poderá revisar a saída antes de mover o resultado para a produção.

Copiar vs Mesclar

Quase tudo será copiado de um site para o outro, mas Categorias e Usuários podem ser mesclados, o que evitará duplicação.

  • Usuários serão mesclados se um usuário em ambos os sites tiver o mesmo endereço de e-mail.
  • Categorias serão mescladas se tiverem o mesmo nome.

Se você deseja fazer qualquer reorganização de seus dados, faça-o antes de mesclar.

Escolha o site de destino

Escolha qual site será o destino dos dados. Este é o que manterá todo o seu estilo e configurações. O outro site terá seus usuários, categorias, tópicos, postagens, uploads, etc., copiados/mesclados no site de destino.

Como fazer

Faça backups de ambos os sites incluindo arquivos e copie-os para o ambiente onde você realizará a mesclagem. É possível que eles sejam de versões diferentes do Discourse, então precisamos que estejam na mesma versão. Eu escolheria usar a versão mais recente do Discourse ao realizar a mesclagem.

Restaure o site de destino no ambiente de mesclagem. Se estiver fazendo isso a partir da linha de comando:

bundle exec ruby script/discourse restore destination-2018-08-02-134227-v2018xxx.tar.gz

Em seguida, extrairemos o outro site.

cd /path/to/data
tar xvzf other-2018-08-02-134227-v2018xxx.tar.gz

A saída incluirá o despejo do banco de dados e os arquivos de upload.

Crie um banco de dados com os dados:

psql
CREATE DATABASE "copyme" ENCODING = 'utf8';
\q
gunzip < /path/to/data/other-2018-08-02-134227-v2018xxx.tar.gz | psql -d copyme

Se você estiver executando a importação em um contêiner Docker oficial (recomendado), você precisará redefinir a senha do postgres para fornecê-la ao script, caso contrário, poderá encontrar um erro de que o usuário postgres não pode acessar o banco de dados.

Para alterar a senha:

sudo -u postgres psql
\password postgres
(digite a nova senha)
\q

Agora é hora de executar o script. Algumas variáveis de ambiente que você definirá:

DB_NAME: nome do banco de dados que está sendo mesclado no site de destino.
DB_HOST: (opcional) nome do host do banco de dados que está sendo mesclado. Deixe em branco se for local.
DB_PASS: senha para o usuário postgres acessar o banco de dados
UPLOADS_PATH: caminho absoluto (do site que está sendo mesclado) do diretório contendo os diretórios “original” e “optimized”. Ex: /path/to/data/uploads/default
SOURCE_BASE_URL: url base do site que está sendo mesclado. Ex: https://meta.discourse.org
SOURCE_CDN: (opcional) url base do CDN do site que está sendo mesclado.

Você pode precisar executar um bundle install antes de executar o script de importação para evitar erros. Para fazer isso:

su discourse -c 'bundle config set --local with generic_import && bundle install'

Na primeira execução, você pode precisar instalar algumas dependências extras para as gems necessárias na importação.

Assim que o bundle estiver concluído, execute a importação.

su discourse -c 'DB_NAME=copyme DB_PASS=password SOURCE_BASE_URL=http://copy.othersite.com UPLOADS_PATH=/shared/import/data/uploads/default bundle exec ruby script/bulk_import/discourse_merger.rb'

Quando terminar, revise a saída em um navegador da web.

Você pode usar a ferramenta remap para atualizar links do fórum antigo.

bundle exec ruby script/discourse remap 'copy.othersite.com' 'hot.newsite.com'

Também reembale todas as postagens com uploads:

rake posts:rebake_match["upload:"]

Se tudo parecer bom, faça um backup do resultado e restaure-o em seu servidor de produção.

bundle exec ruby script/discourse backup
45 curtidas

Parece funcionar, mas quando executo um backup recebo

pg_dump: error: query failed: ERROR:  permission denied for table migration_mappings

Isso é muito estranho.

EDIT: resolvido com

ALTER USER discourse WITH SUPERUSER;
1 curtida

Alguém usou isso recentemente? Como foi?

Além disso, alguém sabe se é possível colocar automaticamente os usuários em um grupo para cada fórum de origem também? (Para facilitar a concessão de permissões para visualizar os tópicos dos fóruns de onde vieram.)

Ficou um pouco complicado. Acho que tive que comentar algumas coisas. Também houve um problema com as imagens da fusão.

Acho que adicionaria todos os usuários do novo site a algum grupo para que eles estivessem nesse grupo quando você os fundisse. Isso seria mais fácil do que fazer isso depois ou como parte da fusão.

2 curtidas

Da última vez que fiz isso, os uploads do site mesclado estavam todos faltando. Obtive uma lista dos uploads de tar tf backupfile.tar.gz e os coloquei em allfiles.txtx e copiei para o diretório de uploads. Este script (que provavelmente não funcionará para você sem modificação) criou um upload para cada um desses arquivos, então refazer as postagens corrigiu todas (ou a maioria?) das imagens ausentes.

def process_uploads
  begin
    # Ler a lista de nomes de arquivos
    filenames = File.readlines('/shared/uploads/allfiles.txt').map(&:strip)
    count = 0

    filenames.each do |filename|
      # Adicionar /shared ao início do nome do arquivo
      filename.gsub!(/\.\//,"")
      full_path = File.join('/shared/uploads/default/original/', filename)

      begin
        # Verificar se o caminho existe e é um arquivo regular (não um diretório)
        count += 1
        
        if File.exist?(full_path) && File.file?(full_path)
          # Abrir o arquivo
          File.open(full_path, 'r') do |tempfile|
            # Criar upload usando os parâmetros especificados
            u = UploadCreator.new(tempfile, 'imported', {}).create_for(-1)
            puts "#{count} -- #{u.id}: #{u.url}"
          end
        else
          puts "Aviso: Caminho não encontrado ou não é um arquivo regular: #{full_path}"
        end
      rescue => e
        puts "Erro ao processar o arquivo #{full_path}: #{e.message}"
        # Continuar com o próximo arquivo mesmo que o atual falhe
        next
      end
    end
  rescue Errno::ENOENT
    puts "Erro: Não foi possível encontrar files.txt"
  rescue => e
    puts "Erro ao ler files.txt: #{e.message}"
  end
end

# Executar o processamento
process_uploads;

Eu obtive as postagens ruins assim:

 bad=Post.where("cooked like '%/images/transparent.png%'")

e depois isso para marcá-las como necessitando de um refazimento:

bad.update_all(baked_version: nil)

Eu estava impaciente, então usei

rake posts:rebake_uncooked_posts

para refazê-las.

2 curtidas

Estou me perguntando se não seria mais fácil converter o fórum discourse que quero mesclar para xenforo (os importadores deles geralmente são excelentes) e depois mesclá-lo com os outros fóruns que quero que façam parte da mesclagem (que por si só serão convertidos de vbulletin para xenforo) e então, finalmente, importar o novo fórum xenforo mesclado para discourse..