disqus.rb 导入脚本使用问题

您好,

我刚搭建好 Discourse,但想从 Disqus 导入我的评论。我注意到有一个很棒的导入脚本,但它似乎对我不起作用。

更新 #2 好的,看来我有一些格式错误的 XML,所以我现在遇到了同样的问题 如这里所述。问题是 Disqus 不再在 XML 导出中包含电子邮件地址,实际上在其仪表板中“隐藏”了它们。因此,除非您添加一些额外的代码,在 create_users 函数中即时生成电子邮件地址,否则可能无法导入评论。

更新: 实际上,我想我应该先退一步。如果不调整脚本顶部的 frozen_string_literal 项,我会得到:

Traceback (most recent call last):
        6: from script/import_scripts/disqus.rb:228:in `<main>'
        5: from script/import_scripts/disqus.rb:228:in `new'
        4: from script/import_scripts/disqus.rb:21:in `initialize'
        3: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/sax/parser.rb:104:in `parse_file'
        2: from /var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/sax/parser.rb:104:in `parse_with'
        1: from script/import_scripts/disqus.rb:176:in `characters'
script/import_scripts/disqus.rb:195:in `record': can't modify frozen String (FrozenError)

所以,也许应该先解决这个问题(在深入探讨下面的问题之前)?

root@discourse:/var/www/discourse# su discourse -c "bundle exec ruby script/import_scripts/disqus.rb"
Loading existing groups...
Loading existing users...
Loading existing categories...
Loading existing posts...
Loading existing topics...

importing users...

importing topics...


Updating topic status

Updating bumped_at on topics

Updating last posted at on users

Updating last seen at on users

Updating first_post_created_at...

Updating user post_count...

Updating user topic_count...

Updating topic users

Updating post timings

Updating featured topic users

Updating featured topics in categories
        4 / 4 (100.0%)  [3222 items/min]  n]  
Resetting topic counters


Done (00h 00min 00sec)

我对 Ruby 了解不多——实际上我完全不懂,但我确实知道足够多的内容来尝试添加一些调试代码,比如 puts "#{id}",看看是否有内容被获取等。例如,我在第 190 行上方添加了 puts "#{target}"puts "#{str}",这样我就能看到它确实在读取文件。

我知道脚本的一部分在工作,IMPORT_FILEIMPORT_CATEGORY 已正确设置。

对于我还能做些什么来排查/调试,有什么建议吗?

谢谢!:blue_heart:

几个月前我处理过这个议题。我想通过将 target[sym] << str 替换为 target[sym] += str 解决了 frozen_string_literal 问题,不过只需将第一行中的 true 改为 false 应该就可以了。

我隐约记得它当时也没起什么作用,就像对你一样,但我记不清具体原因了,在我当时的修改中也看不出明显的线索。而且,由于这次导入需要集成到一个现有网站中,我不得不进行了一些其他调整,所以恐怕我的代码对你没什么帮助。

@pfaffman!感谢你抽空回复!

我也尝试过使用 target[sym] += str,并将第一行改为 false。我认为我上面的第 2 条更新是正确的。代码试图将 email 中的值传递给另一个函数,但由于该值为 null 或空,导致另一个函数报错崩溃了 :stuck_out_tongue_closed_eyes:

需要引入一些新代码来处理 email 为空的情况:要么将其替换为默认值,要么生成一个新的唯一值,或者在 email 为空时跳过创建新用户。

    @parser.posts.each do |id, p|
      p[:author_email] = "#{p[:author_username]}@nowhere.invalid" unless p[:author_usrname]
      next if p[:is_spam] == 'true' || p[:is_deleted] == 'true'
      puts "name: #{p[:author_name]}, username: #{p[:author_username]}, email: #{p[:author_email]} "
      by_email[p[:author_email]] = { name: p[:author_name], username: p[:author_username] }
    end

如果您修复了问题,且确认 Disqus 导入功能确实存在缺陷,欢迎提交 Pull Request 以改进它!

我总是打算……

好的!我通过以下方式解决了这个问题:

    @parser.posts.each do |id, p|
      p[:author_username] = "#{p[:author_name]}" unless p[:author_username]
      p[:author_email] = "#{p[:author_username]}@disqus.sucks" unless p[:author_email]
      next if p[:is_spam] == 'true' || p[:is_deleted] == 'true'
      puts "name: #{p[:author_name]}, username: #{p[:author_username]}, email: #{p[:author_email]}"
      by_email[p[:author_email]] = { name: p[:author_name], username: p[:author_username] }
    end

    @parser.threads.each do |id, t|
      t[:author_username] = "#{t[:author_name]}" unless t[:author_username]
      t[:author_email] = "#{t[:author_username]}@disqus.sucks" unless t[:author_email]
      by_email[t[:author_email]] = { name: t[:author_name], username: t[:author_username] }
    end

我还设置了 frozen_string_literal: false

我进展得更远了,但现在某个 的东西是 nil。我会继续排查和尝试,但非常需要帮助,我承诺会将我的发现回馈回去。

我应用了本线程中的补丁,但在导入话题时卡在了这里:

Traceback (most recent call last):
        5: from script/import_scripts/disqus.rb:236:in `\u003cmain\u003e'
        4: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
        3: from script/import_scripts/disqus.rb:29:in `execute'
        2: from script/import_scripts/disqus.rb:70:in `import_topics_and_posts'
        1: from script/import_scripts/disqus.rb:70:in `each'
script/import_scripts/disqus.rb:84:in `block in import_topics_and_posts': undefined method `topic' for nil:NilClass (NoMethodError)

好吧。我觉得今晚我搞不定这个了。

我已经弄明白 find_remote() 对某条评论返回了 nil,但我完全不知道这意味着什么,也不明白这为何重要。我怀疑这与 HTTP/HTTPS 有关,所以出于绝望,我打算把我 Disqus 导出文件中的所有 URL 从 HTTP 改为 HTTPS,然后听天由命。

非常欢迎任何建议。

[更新!]

我目前的猜想:如果 Disqus 评论所在的帖子链接对应的 Disqus 线程已不存在(例如来自 1853 年的 Tumblr 博客),那么这个导入脚本就会彻底崩溃。

万一我猜对了,有没有更熟悉代码的人能建议如何修改导入器,让它能够愉快地跳过这类线程和评论?

如果我没猜对,嗯,那我大概会再回复这条消息,分享更多发现。:stuck_out_tongue:

[更新!]

我手动删除了所有来自链接已失效线程的评论。这似乎足以成功导入我所有的 Disqus 评论。因此,我认为,如果有人能读懂这个脚本的代码并据此进行修复,那就太好了。我觉得我自己做不到。

至少我希望这些文字能帮助到接下来追随我的那位可怜人。祝好运。

再见。