Migrar um fórum IPB 3.1 para Discourse

Olá, Comunidade Discourse,

Gostaria de compartilhar minha experiência com a importação de um fórum IPB 3.1 para o Discourse 2.1, na esperança de que isso seja útil para outros.

Um breve resumo sobre a Comunidade:

  • Tópico: Yii PHP Framework (discussões e suporte relacionados a código)
  • Membros: ~26 mil
  • Tópicos: ~64 mil
  • Posts: ~293 mil

A importação levou 27h 46min em uma máquina com 16 GB de RAM e 4 núcleos de CPU.

Requisitos da Importação:

  • Manter os membros, mas limpar todas as contas de SPAM (~250 mil contas, das quais ~26 mil permanecem após a limpeza)
  • Implementar SSO a partir do site (as contas de usuário não são gerenciadas pelo Discourse)
  • Manter tópicos, posts e categorias com seus URLs originais para que os resultados de pesquisa na web continuem funcionando, bem como outros links de plataformas como o Stackoverflow

Isso é baseado em Migrating from Invision Power Board to Discourse - #23 by pfaffman, então obrigado a @pfaffman pelo excelente trabalho feito no importador.

Preparação

Exportando Dados do IPB

mysqldump <databasename> > /tmp/ipb.sql
cd /var/www/yiiframework.com/forum/ && tar czvf uploads.tgz uploads/

Copie o dump SQL e os uploads para o novo servidor e coloque-os em /var/discourse/shared/standalone/.
Estou assumindo uma configuração simples do Docker do Discourse aqui.

Qual script usar?

Existem dois scripts de importação, ipboard.rb e ipboard3.rb. O script ipboard3.rb parece muito bruto e também não se encaixa no esquema de tabelas que temos, então optei pelo ipboard.rb.

A versão atual do script de importação ipboard.rb não lida bem com anexos e também não converte tags de código, o que é muito importante para nós, já que falamos muito sobre código PHP. Portanto, fiz as seguintes alterações no script:

Tornando os Anexos Carregados Disponíveis

O script de importação substitui os anexos de post por URLs para o arquivo carregado.
Se você pretende manter sua instância IPB online no URL onde estava anteriormente, basta especificar o URL (UPLOADS é uma configuração do script de importação, veja abaixo) para o diretório de uploads e pronto:

UPLOADS="https://www.yiiframework.com/forum/uploads"

Mas estamos importando para o Discourse para remover completamente o fórum antigo, então precisamos colocar os uploads em outro lugar. Se você estiver usando um proxy nginx na frente do Discourse, pode configurá-lo para servir os arquivos carregados a partir de um diretório no servidor. Coloque o seguinte na parte server da configuração do nginx:

location /ipb_uploads/ {
    alias /var/www/ipb_uploads/;
}

E configure o URL de anexo (veja abaixo) assim:

UPLOADS="https://forum.yiiframework.com/ipb_uploads"

Configurando o MySQL no contêiner do Discourse

Inicie um shell bash no contêiner do aplicativo Discourse:

docker exec -it app bash

Dentro do contêiner, instale o MySQL e importe o banco de dados:

apt-get install mysql-server mysql-client libmysqlclient-dev
service mysql start
echo "create database ipb" | mysql -uroot -p
mysql -uroot -p ipb < /shared/ipb.sql

Quando tentei a primeira importação para testar o script, ela rodou por vários dias para importar 200 mil usuários, dos quais sabíamos que uma grande quantidade eram contas de SPAM. Então, criamos algumas consultas SQL para excluir contas que nunca haviam postado nada:

Note que vamos usar SSO, então os usuários excluídos serão recriados quando fizerem login.
Se você não for usar SSO, seus critérios para excluir usuários podem ser diferentes.
Você pode importar seus dados sem limpá-los.

mysql -uroot -p
# então aplique as consultas de limpeza

Em seguida, precisamos instalar as dependências para o script de importação:

cd /var/www/discourse
echo "gem 'mysql2'" >> Gemfile
echo "gem 'reverse_markdown'" >> Gemfile
bundle install --no-deployment

Para permitir o acesso ao banco de dados Postgres do Discourse, substitua peer por trust em /etc/postgresql/10/main/pg_hba.conf. Note que 10 representa a versão do postgres; se o arquivo não existir em sua configuração, substitua 10 pela versão do postgres que você está executando atualmente.
Reinicie o Postgres para carregar as alterações: service postgresql restart

Importando

Prepare os avatares e os arquivos carregados:

mkdir /shared/imports
mv /shared/uploads.tgz /shared/imports
cd /shared/imports && tar xzvf uploads.tgz

Execute o script do importador:

cd /var/www/discourse
DB_HOST="localhost" DB_NAME="yiisite" DB_USER="root" DB_PW="root" TABLE_PREFIX="ipb_" IMPORT_AFTER="1970-01-01" UPLOADS="https://www.forum.yiiframework.com/ipb_uploads" AVATARS_DIR="/shared/imports/uploads/" USERDIR="user" bundle exec ruby script/import_scripts/ipboard.rb | tee import.log

Certifique-se de ajustar o URL UPLOADS conforme discutido acima, pois os uploads serão incluídos nos posts como links para o arquivo de upload original.

Limpeza

Se tudo correu bem, faça a limpeza com service mysql stop, apt-get purge mysql-server, rm -rf /var/lib/mysql

Configurando o redirecionamento de URL

Para manter os URLs existentes do fórum intactos, o script de importação cria permalinks para cada tópico que refletem o URL de tópicos e categorias no IPB.
No entanto, esses permalinks não cobrem links para posts específicos em um tópico ou páginas diferentes.
Para que esses URLs funcionem corretamente, você precisa configurar algumas regras de reescrita de URL; há 3 opções:

  • Usar a configuração permalink normalizations no Discourse para remover partes desnecessárias dos URLs
  • Regras de reescrita no nginx, se você tiver um proxy nginx na frente do Discourse
  • Se o fórum antigo estava em um URL/Host diferente do Discourse, você pode ter um script personalizado para reescrever os URLs (foi isso que fiz)

Aqui está o código PHP que usamos para redirecionamento de URL:

Recursos Relacionados

18 curtidas

Hello,

sorry to bump this old topic, but i’m also planning to migrate from IPB (v3.4) to Discourse and I’m following this howto. So i figured out I will directly reply in this topic instead of creating a new one.

mysql package is no longer in the distribution, so I followed this guide
basically:

wget http://repo.mysql.com/mysql-apt-config_0.8.13-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb
sudo apt update
sudo apt install mysql-server mysql-client libmysqlclient-deb
service mysql start

but then i get below error
mysql: unrecognized service

any idea how I can start mysql ?

Thank you

Houve erros ao executar os comandos que deveriam tê-lo instalado? Recomendo uma pesquisa no Google.

Além disso, você pode querer usar o script ipb que faz parte do Discourse em vez daquele referenciado no OP.

Existe alguma atualização para este script, pois ele não funcionará com IPB 4x e também não é compatível com o Discourse, pois a estrutura das tabelas mudou e o script permaneceu o mesmo?

1 curtida

Estou fazendo uma importação do ipboard agora. Tive que remover algumas tabelas e linhas de algumas das consultas. Parece que eles têm muitas configurações de tabela diferentes.

Obter as postagens brutas do ipb em markdown também é complicado.

Se você tiver um orçamento, pode entrar em contato comigo. Posso conseguir o código que tenho para a importação que estou fazendo agora, mas provavelmente precisará de trabalho para sua configuração específica.

2 curtidas

to help you, IPB 4x tables is as follow:

mysql> SHOW TABLES;
+-------------------------------------------+
| Tables_in_ipboard                         |
+-------------------------------------------+
| ipb_bbcode_mediatag                       |
| ipb_ccs_folders                           |
| ipb_cms_blocks                            |
| ipb_cms_containers                        |
| ipb_cms_custom_database_1                 |
| ipb_cms_custom_database_2                 |
| ipb_cms_database_categories               |
| ipb_cms_database_comments                 |
| ipb_cms_database_fields                   |
| ipb_cms_database_fields_reciprocal_map    |
| ipb_cms_database_fields_thumbnails        |
| ipb_cms_database_reviews                  |
| ipb_cms_database_revisions                |
| ipb_cms_databases                         |
| ipb_cms_folders                           |
| ipb_cms_media                             |
| ipb_cms_media_folders                     |
| ipb_cms_page_database_map                 |
| ipb_cms_page_widget_areas                 |
| ipb_cms_pages                             |
| ipb_cms_template_conflicts                |
| ipb_cms_templates                         |
| ipb_cms_url_store                         |
| ipb_core_achievements_log                 |
| ipb_core_achievements_log_milestones      |
| ipb_core_achievements_rules               |
| ipb_core_acp_notifcations_dismissals      |
| ipb_core_acp_notifications                |
| ipb_core_acp_notifications_preferences    |
| ipb_core_acp_search_index                 |
| ipb_core_acp_tab_order                    |
| ipb_core_acronyms                         |
| ipb_core_admin_login_logs                 |
| ipb_core_admin_logs                       |
| ipb_core_admin_permission_rows            |
| ipb_core_advertisements                   |
| ipb_core_alerts                           |
| ipb_core_alerts_seen                      |
| ipb_core_announcements                    |
| ipb_core_anonymous_posts                  |
| ipb_core_api_keys                         |
| ipb_core_api_logs                         |
| ipb_core_api_webhook_fires                |
| ipb_core_api_webhooks                     |
| ipb_core_applications                     |
| ipb_core_approval_queue                   |
| ipb_core_archive_log                      |
| ipb_core_archive_restore                  |
| ipb_core_attachments                      |
| ipb_core_attachments_map                  |
| ipb_core_automatic_moderation_pending     |
| ipb_core_automatic_moderation_rules       |
| ipb_core_automatic_moderation_types       |
| ipb_core_badges                           |
| ipb_core_banfilters                       |
| ipb_core_bulk_mail                        |
| ipb_core_cache                            |
| ipb_core_club_pages                       |
| ipb_core_clubs                            |
| ipb_core_clubs_fields                     |
| ipb_core_clubs_fieldvalues                |
| ipb_core_clubs_memberships                |
| ipb_core_clubs_node_map                   |
| ipb_core_contact_verify                   |
| ipb_core_content_featured                 |
| ipb_core_content_meta                     |
| ipb_core_deletion_log                     |
| ipb_core_dev                              |
| ipb_core_edit_history                     |
| ipb_core_editor_stored_replies            |
| ipb_core_email_templates                  |
| ipb_core_emoticons                        |
| ipb_core_error_logs                       |
| ipb_core_file_logs                        |
| ipb_core_file_storage                     |
| ipb_core_files                            |
| ipb_core_files_temp                       |
| ipb_core_follow                           |
| ipb_core_follow_count_cache               |
| ipb_core_geoip_cache                      |
| ipb_core_googleauth_used_codes            |
| ipb_core_group_promotions                 |
| ipb_core_groups                           |
| ipb_core_hooks                            |
| ipb_core_hooks_files                      |
| ipb_core_ignored_users                    |
| ipb_core_incoming_emails                  |
| ipb_core_inline_messages                  |
| ipb_core_ips_bulletins                    |
| ipb_core_item_markers                     |
| ipb_core_item_member_map                  |
| ipb_core_item_redirect                    |
| ipb_core_item_statistics_cache            |
| ipb_core_javascript                       |
| ipb_core_leaders                          |
| ipb_core_leaders_groups                   |
| ipb_core_like_cache                       |
| ipb_core_log                              |
| ipb_core_login_failures                   |
| ipb_core_login_handlers                   |
| ipb_core_login_links                      |
| ipb_core_login_methods                    |
| ipb_core_mail_error_logs                  |
| ipb_core_member_badges                    |
| ipb_core_member_history                   |
| ipb_core_member_privacy_actions           |
| ipb_core_member_ranks                     |
| ipb_core_member_recognize                 |
| ipb_core_member_status_replies            |
| ipb_core_member_status_updates            |
| ipb_core_members                          |
| ipb_core_members_feature_seen             |
| ipb_core_members_known_devices            |
| ipb_core_members_known_ip_addresses       |
| ipb_core_members_logins                   |
| ipb_core_members_warn_actions             |
| ipb_core_members_warn_logs                |
| ipb_core_members_warn_reasons             |
| ipb_core_menu                             |
| ipb_core_message_posts                    |
| ipb_core_message_topic_user_map           |
| ipb_core_message_topics                   |
| ipb_core_moderator_logs                   |
| ipb_core_moderators                       |
| ipb_core_modules                          |
| ipb_core_notification_defaults            |
| ipb_core_notification_preferences         |
| ipb_core_notifications                    |
| ipb_core_notifications_pwa_keys           |
| ipb_core_notifications_pwa_queue          |
| ipb_core_oauth_authorize_prompts          |
| ipb_core_oauth_clients                    |
| ipb_core_oauth_server_access_tokens       |
| ipb_core_oauth_server_authorization_codes |
| ipb_core_output_cache                     |
| ipb_core_permission_index                 |
| ipb_core_pfields_content                  |
| ipb_core_pfields_data                     |
| ipb_core_pfields_groups                   |
| ipb_core_plugins                          |
| ipb_core_points_log                       |
| ipb_core_polls                            |
| ipb_core_post_before_registering          |
| ipb_core_profanity_filters                |
| ipb_core_profile_completion               |
| ipb_core_profile_steps                    |
| ipb_core_question_and_answer              |
| ipb_core_queue                            |
| ipb_core_ratings                          |
| ipb_core_rc_author_notification_text      |
| ipb_core_rc_comments                      |
| ipb_core_rc_index                         |
| ipb_core_rc_reports                       |
| ipb_core_reactions                        |
| ipb_core_referral_banners                 |
| ipb_core_referrals                        |
| ipb_core_reputation_index                 |
| ipb_core_reputation_leaderboard_history   |
| ipb_core_reputation_levels                |
| ipb_core_rss_export                       |
| ipb_core_rss_import                       |
| ipb_core_rss_imported                     |
| ipb_core_s3_deletions                     |
| ipb_core_saved_charts                     |
| ipb_core_search_index                     |
| ipb_core_search_index_item_map            |
| ipb_core_search_index_tags                |
| ipb_core_security_answers                 |
| ipb_core_security_questions               |
| ipb_core_seo_meta                         |
| ipb_core_sessions                         |
| ipb_core_share_links                      |
| ipb_core_sitemap                          |
| ipb_core_social_promote                   |
| ipb_core_social_promote_content           |
| ipb_core_social_promote_sharers           |
| ipb_core_soft_delete_log                  |
| ipb_core_solved_index                     |
| ipb_core_spam_service_log                 |
| ipb_core_spam_whitelist                   |
| ipb_core_statistics                       |
| ipb_core_store                            |
| ipb_core_stream_subscriptions             |
| ipb_core_streams                          |
| ipb_core_sys_conf_settings                |
| ipb_core_sys_cp_sessions                  |
| ipb_core_sys_lang                         |
| ipb_core_sys_lang_words                   |
| ipb_core_sys_login                        |
| ipb_core_sys_settings_titles              |
| ipb_core_sys_social_group_members         |
| ipb_core_sys_social_groups                |
| ipb_core_tags                             |
| ipb_core_tags_cache                       |
| ipb_core_tags_perms                       |
| ipb_core_tasks                            |
| ipb_core_tasks_log                        |
| ipb_core_theme_conflict                   |
| ipb_core_theme_content_history            |
| ipb_core_theme_css                        |
| ipb_core_theme_resources                  |
| ipb_core_theme_settings_fields            |
| ipb_core_theme_settings_values            |
| ipb_core_theme_templates                  |
| ipb_core_themes                           |
| ipb_core_upgrade_history                  |
| ipb_core_validating                       |
| ipb_core_view_updates                     |
| ipb_core_voters                           |
| ipb_core_widget_areas                     |
| ipb_core_widget_trash                     |
| ipb_core_widgets                          |
| ipb_custom_bbcode                         |
| ipb_forums_answer_ratings                 |
| ipb_forums_archive_posts                  |
| ipb_forums_archive_rules                  |
| ipb_forums_forums                         |
| ipb_forums_posts                          |
| ipb_forums_question_ratings               |
| ipb_forums_topic_mmod                     |
| ipb_forums_topics                         |
| ipb_forums_view_method                    |
| ipb_nexus_alternate_contacts              |
| ipb_nexus_billing_agreements              |
| ipb_nexus_cart_uploads                    |
| ipb_nexus_coupons                         |
| ipb_nexus_customer_addresses              |
| ipb_nexus_customer_cards                  |
| ipb_nexus_customer_fields                 |
| ipb_nexus_customer_spend                  |
| ipb_nexus_customers                       |
| ipb_nexus_donate_goals                    |
| ipb_nexus_donate_logs                     |
| ipb_nexus_eom                             |
| ipb_nexus_fraud_rules                     |
| ipb_nexus_invoice_tracker                 |
| ipb_nexus_invoices                        |
| ipb_nexus_licensekeys                     |
| ipb_nexus_member_subscription_packages    |
| ipb_nexus_member_subscriptions            |
| ipb_nexus_notes                           |
| ipb_nexus_package_base_prices             |
| ipb_nexus_package_fields                  |
| ipb_nexus_package_filters                 |
| ipb_nexus_package_filters_map             |
| ipb_nexus_package_filters_values          |
| ipb_nexus_package_groups                  |
| ipb_nexus_package_images                  |
| ipb_nexus_packages                        |
| ipb_nexus_packages_ads                    |
| ipb_nexus_packages_products               |
| ipb_nexus_paymethods                      |
| ipb_nexus_payouts                         |
| ipb_nexus_product_options                 |
| ipb_nexus_purchases                       |
| ipb_nexus_referral_rules                  |
| ipb_nexus_reviews                         |
| ipb_nexus_ship_orders                     |
| ipb_nexus_shipping                        |
| ipb_nexus_support_default_content         |
| ipb_nexus_support_departments             |
| ipb_nexus_support_fields                  |
| ipb_nexus_support_notify                  |
| ipb_nexus_support_ratings                 |
| ipb_nexus_support_replies                 |
| ipb_nexus_support_request_log             |
| ipb_nexus_support_requests                |
| ipb_nexus_support_severities              |
| ipb_nexus_support_staff_dpt_order         |
| ipb_nexus_support_staff_preferences       |
| ipb_nexus_support_statuses                |
| ipb_nexus_support_stock_actions           |
| ipb_nexus_support_streams                 |
| ipb_nexus_support_tracker                 |
| ipb_nexus_support_views                   |
| ipb_nexus_tax                             |
| ipb_nexus_transactions                    |
| ipb_rc_reports_index                      |
| x_utf_ipb_convert_session                 |
| x_utf_ipb_convert_session_tables          |
+-------------------------------------------+