Migrate a vBulletin 4 forum to Discourse

Hi. Just want to share my solution.
As for the problems with quotes. As I said before, i’m was facing with problems - regexp not capture quotes then:

  • username and post id may be enclosed in double quotes
  • nested quotes

I decided to do a search and replace using a different logic. Instead of searching for tags and their contents, I used a regular expression that searches only for tags:

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

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

and then little change the determining the source of a quote:

      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

Also, I change the spoiler’s code. Instead of:

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

that blured text, I convert it to details tag:

    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

Because it just so happens that in the vbulletin world - sploiler it is not the blurred content, but rather the collapsed content. So I think it is much more appropriate for the vbulletin import script to convert spoilers to details instead of the blurred spoiler.

I also noticed the mention tag. In my case, in vbulletin, the mentions looked like this:
[mention=XXX]username[/mention]

The regular expression used in the script does not take into account that the tag may contain the user id.

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

I fixed this in my own way too:

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

This is not true when I started migrating my 24 year old vBulletin forum running vB 3. There were multiple incompatibilities and other issues with the script. However, I put in a lot of effort in creating an importer for vBulletin 3 based on the the script for vB4.

The improved script is included with Discourse, it is called vbulletin3.rb. Usage of the vB3 import script is the same as described in this how-to. Just execute bundle exec ruby script/import_scripts/vbulletin3.rb instead.

The vBulletin3 has some significant changes/improvements:

  1. Forum permissions are copied
  2. Forum moderator groups are created
  3. Joinable user groups are created with proper configuration
  4. Forum nesting in imported up to 3 levels deep (maximum of Discourse)
  5. Permalinks are registered for all threads and posts, preventing link rot
  6. Some basic forum settings are copied over (e.g. title, notification email, company name)
  7. Polls are imported
  8. Major improvements to the bbcode → markdown conversion
  9. URL deep links to threads, post, attachments are converted to discourse references, this requires setting the environment variable FORUM_URL to forum.hostname/path (no protocol).

Instead of trying to convert vBulletin private messages to Discourse private messages users will instead receive a system private message containing an archive of the private messages they had. vBulletin’s PM construction is not really compatible with Discourse. Trying to convert it would also expose some privacy depending how people used PMs in vBulletin.

As it is probably also the case with other importers, it can take quite a bit of time to convert. The conversion script took 5.5 hours on my workstation for 7k users, 16k threads, 415k posts. I have no idea how much time it took for the post processing, I let that run over night. From start to end the forum was down for 30 hours. In the end I’m happy with the result.

2개의 좋아요

Now that’s a throwback :slight_smile:

Your forum looks very nice. I like the alternating colors on the topic rows.

It seems both this thread and the importer are well out of date at this point. I’ve fixed a few problems with help from this thread, but I’m stuck now on the following on the user import step, anyone know how to fix it?

<internal:timev>:286:in at’: can’t convert NilClass into an exact number (TypeError)`

Either the query is wrong or somehow the table is missing a value

It’s rather bizarre to respond to this so many years later, but I’m doing a VB import now with the bulk importer and a bunch of images were missing and the reason is that they moved the attachment filename to a different field.

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

the NUMBER.attach file is now the filedataid field, not the attachment_idfield. So that query needs to be updated in the script.

vBulletin 4.25 포럼을 Discourse로 마이그레이션해 달라는 요청을 받았습니다… 이 스레드를 읽으면서 복잡한 감정이 드네요… 가능해 보이지만, 엄청난 수고와 시간 소모가 될 것 같습니다(지금 그 둘 다 피하고 싶은데)…

vBulletin 4.25용 업데이트된 스크립트가 어디에 있나요? 공식 페이지에는 3과 5 버전만 보입니다.

음, bulk imports 디렉토리에 몇 달 전만 만들어진 vbulletinvbulletin5 스크립트가 있습니다. 이 벌크 임포트를 실행하는 것은 꽤 까다롭고, 문서화도 잘 되어 있지 않습니다.

저는 100건 이상의 임포트를 수행해 봤는데, 스크립트를 어떤 이유로든 조정하지 않고 완료한 경우는 한 번도 없었던 것 같습니다.

정말 Ruby를 제대로 배우기 전에 여러 개의 임포트 스크립트를 작성했습니다(하지만 1980년대 중반에 한 교수님이 프로그래밍 언어 수업 후 주말과 책만 있으면 어떤 언어든 알 수 있다고 확신을 주셨는데, 대체로 맞았습니다.)

하지만 네, 상상하시는 것만큼이나, 혹은 그 이상으로 고통스럽고 시간을 많이 잡아먹을 가능성이 높습니다.

vbulletin 스크립트가 꽤 잘 작동할 것 같습니다. 100만 개 이상의 게시물과 사용자가 없는 한 벌크 임포트 스크립트를 권장하지는 않을 것 같습니다.

1개의 좋아요

도와줘서 고마워요 :slight_smile:

주말에 뭘 해야 할지 결정을 내려야 할 것 같네요 :smiley:

1개의 좋아요

이 부분에 대한 도움을 정말 많이 받고 싶습니다 :face_with_spiral_eyes:

스레드를 읽어보고 여기에서 본 몇 가지 단계를 따라갔지만 막혀버렸습니다.

  1. VPS에 ssh로 접속
  2. Docker 이미지로 진입
  3. mariadb-server 설치
  4. mysql 명령을 실행하여 데이터베이스를 만들려는데 ‘can’t connect to local server through socket’ 오류가 나요

여기 있는 설명은 몇 년 전 것인데, 몇몇 사람이 같은 오류를 겪은 걸 봤지만 해결책은 보이지 않네요.

최근에 이 과정을 해보신 분이 계신가요? 올바른 방향으로 이끌어줄 수 있을까요? 어디선가 놓치고 있는 단계별 가이드가 있는 것 같지는 않은데, 혹시 있을까요?

수정: 추가로 말씀드리면, 온갖 시도를 해본 끝에 로컬 호스트(도커가 아닌)에 mariadb의 도커 이미지를 설치하고 포트 노출을 시도했습니다. 이제 도커 이미지에서 DB에 연결할 수는 있는데… 스크립트를 실행하면 Gemfile: Undefined local variable or method ‘mysql2’ 오류가 나요. gemfile 설치를 시도해봤지만 실패하네요… 더 이상 트러블슈팅하기 전에, 오래된 정보와 잠재적으로 오래된 패키지를 사용하고 있다는 느낌이 들어서요…정말 혼란스럽고 지침이 필요해요!

도움 주시면 감사하겠습니다!

…나는 계속 시도했고 마침내 스크립트가 실행되는 단계까지 도달했습니다! 그러나 실행을 시작하면 다음과 같은 오류가 발생합니다:

"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- [................]"

…그리고 이제 문제 해결 능력을 거의 한계에 도달한 것 같습니다.

/var/www/discourse에서 시작하는 것이 차이를 만드는지 확신은 없지만, 저는 항상 그렇게 합니다. OP에서 권장하는 방법은 다음과 같습니다.

그 오류는 알지 못합니다.

1개의 좋아요

어젯밤에 포기할 때까지 몇 시간 동안 '조사’를 한 결과, 제 능력 범위를 벗어난 것들을 너무 많이 만져서 오히려 더 큰 문제를 일으키고 있는 건 아닌지 걱정되었습니다. 또한 누군가가 최근에 이 작업을 수행한 적이 있다면 제가 놓치고 있는 마법 같은 단계가 있는지 알고 싶었습니다. 반복되는 토끼굴에 빠져들기보다는 말이죠. :winking_face_with_tongue:

새로운 문제가 있을 수 있습니다. 며칠 전 mbox 가져오기를 실행했는데, 그 과정에서 에러를 유발한 것과 동일한 코드가 호출된다고 추정됩니다.

아, 저는 컨테이너에서 진행했고 이 설명서는 개발 환경을 위한 것이네요. 개발 환경을 설정하셨나요? 정상적으로 작동하나요? VPN 환경에서는 설정이 까다로울 수 있습니다.

내일 다시 초기화해서 시도해볼 거야. 오늘 밤 두통이 심해서.

결과 알려줄게 :slightly_smiling_face:

1개의 좋아요

개발 환경을 설정했나요? 그게 첫 단계였나요?

호스트 VPS를 통해 시도해 보고, 나중에 컨테이너를 통해 어정쩡하게 처리했습니다. 작업을 마칠쯤에는 어디서 뭘 했는지 헷갈리기 시작했죠. 아마도 제 실력이 부족해서 그런 것 같습니다… 내일 처음부터 다시 시작하겠습니다.

VM에서 작업하는 경우, 컨테이너에서 수행하는 것이 더 쉬울 수 있습니다. 다른 import how-to 예제를 참고해 보세요 (mysql 템플릿이 포함되어 있을 것입니다).

컨테이너에 진입한 후, Gem 파일을 편집하고 bundle install을 실행하게 될 것입니다.

mysql 또는 Mariadb를 위해 컨테이너를 사용하는 것이 합리적일 수 있습니다. (다만, 컨테이너들이 서로를 인식할 수 있도록 해야 합니다)

1개의 좋아요

흥분되는 소식이 있습니다…

스크립트를 실행하는 데 성공했습니다(모든 작업이 끝나면 가이드를 만들 예정입니다). 사용자 그룹은 가져오기 완료되었지만, 사용자 가져오기 단계에서 멈춰 있습니다. 타임존 변수 때문인 것 같습니다.

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 script/import_scripts/vbulletin.rb:1027:in `<main>'

스크립트의 기본값은 "America/Los Angeles"입니다. vBulletin 포럼은 (GMT) Western Europe Time, London, Lisbon, Casablanca)으로 설정되어 있고, 데이터를 가져오는 대상인 Discourse 인스턴스에는 America/Los Angeles와 Europe/Paris 두 항목이 있습니다.

어떤 것을 선택해야 하는지 아시나요?

어떤 것을 선택하든 크게 중요하지 않습니다.

날짜가 스크립트가 기대하는 방식으로 저장되지 않은 것 같습니다.

1개의 좋아요