将SMF2论坛迁移到Discourse

我们尝试了,但遇到了以下问题:所有帖子都已导入,但主题标题未显示,外部图片未渲染。 当前的 SMF2 论坛是:https://forum.mundofotografico.com.br 我们正在尝试迁移到 Discourse,地址是:https://discourse.fotografos.online - 所有主题和正确的描述都未成功导入,图片也未加载……请帮忙! @marcozambi @miligraf @FireAllianceNX @pfaffman

我才刚开始 SMF 迁移过程,目前正在将帖子导入一个测试实例,速度大约是每小时 1000 篇,到目前为止一切顺利,除了 MySQL 性能脚本,MySQL 不知道为什么不喜欢“ALTER USER”命令。我手动执行了“CREATE USER”,之后一切都正常。

我读了关于已删除用户的评论,但我无法轻易创建新用户/假电子邮件来覆盖我所有的已删除用户(我的论坛已经运行了 20 多年,我拥有的已删除用户可能比真实用户还多)。我估计有 4000-5000 个已删除用户。并非所有用户都发过帖子,但很多用户都发过帖子,所以我可能有很多数百个“丢失”的用户。

帖子被导入为属于“system”,这并不是很理想。我曾想过以下方法是否可行。

  1. 导入前,创建一个虚拟用户,例如“Deleted User”。
  2. 找出“Deleted User”的用户编号。
  3. 修改 smf2.rb 中的行“user_id: user_id_from_imported_user_id(message[:id_member]) || -1,”,并将“-1”替换为“Deleted User”的用户编号(我认为系统用户是-1?)

这会奏效吗?另外,smf2.rb 中还有其他地方需要进行类似的更改吗?

你好,你说的“已删除”是指他们确实从 SMF 数据库中删除了,还是他们仍然在数据库中,用户名和电子邮件仍然存在但被标记为已暂停?那些“已删除”用户的帖子在 SMF 中目前是如何显示的?

我正在进行一次从 Drupal 到 Discourse 的大规模迁移,这也是从一个拥有大量已暂停用户的老牌论坛迁移。我绝对想在 Discourse 中保留那些相同的已暂停用户名及其关联的电子邮件地址,因此我必须为 Discourse 的 Drupal 导入脚本添加该功能。基本上,该脚本会像正常活动用户一样导入所有用户,如果他们有任何公开可见的帖子,这些帖子也会像在原始论坛上一样被导入。然后在过程的最后,我添加了一个我从另一个导入脚本中提取的功能,该功能会遍历 Drupal 数据库,如果用户被标记为已暂停,则也会暂停 Discourse 帐户。你可以在我在这里的帖子历史记录中看到该代码。

1 个赞

您好。用户实际上已被删除,也就是说,smf_member 表中不再有他们的记录。SMF 没有暂停用户的功能。您可以禁止用户,但这似乎不适用于用户已故或对爱好/论坛失去兴趣的帐户。从数据保护的角度来看,这也不是很合适。

SMF 帖子为每条记录存储两个字段……用户会员编号,已删除用户的此字段设置为零,以及发帖人姓名,其中包含发帖人的用户名。因此,您可以看到哪个用户发布了消息,但用户不再有任何详细信息(电子邮件、全名等)。他们的帖子在显示时会带有“访客”标记。

我想我可以为每个发布了会员 ID 为零的消息的用户创建一个新帐户,并为其分配一个虚拟电子邮件地址,然后将用户标记为暂停。如果我使用一些独特但可识别的格式,我可以通过虚拟电子邮件帐户的格式来标记帐户。但在某些情况下,这感觉有点奇怪……为我知道在 10-15 年前就已故的人创建帐户!

不过,我有时间考虑这个问题……迁移部分成功了,但我现在必须弄清楚为什么附件没有附加,论坛内链接没有修改,以及迁移用户的密码为什么不起作用。可能还有其他问题,但我会先解决这些问题,然后再看看还会出现什么问题。

你是说 Postgres 吗?我不确定这是怎么回事。

我的做法是,如果用户 ID 为 0,则使用用户名作为 ID。然后,如果 find_username_by_import_id 找不到用户,则创建该用户,将电子邮件地址设置为 fake_email(这是 base.rb 中用于生成假电子邮件地址的函数),并将用户名设置为你拥有的用户名。然后,如果你有雄心,可以在脚本末尾暂停所有电子邮件地址中包含 @email.invalid 的用户。他们不会活跃,所以我不认为不暂停他们会有多大影响。

另一种方法是执行一个查询,以某种方式生成一个所有已删除用户的列表,然后在开始处理帖子之前创建它们,但这似乎更难。

如果你想创建一个“已删除用户”用户,并让所有这些帖子都归该用户所有,而不是“system”,你可以这样做,只需将“-1”替换为“已删除用户”的用户编号。你可以将其创建为常规用户,或者做一些花哨的事情,让它的用户 ID 为“-2”或类似的值。

在某些系统中,这是因为附件有时在帖子的正文中,而其他附件记录在数据库中。

你是否在运行导入后安装了 Migrated password hashes support 插件(它在至少某些情况下会干扰运行导入)。SMF2 的密码哈希方式是否与 smf 的方式 相同?

抱歉,脚本名称弄错了。这是第一篇帖子中提到的 MySQL 脚本

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

感谢您关于用户,特别是 fake_email 的建议。我的第一个任务是学习足够的 Ruby 来修改导入脚本!

SMF2 附件是数据库中的记录。经过更深入的研究,看起来有些已经导入,但几万条中只有几百条。我会继续研究,看看能否找出原因。

啊,这可能就是我遗漏的地方!我很确定 SMF2 使用与 SMF1 相同的哈希(我记得是加盐的 MD5),所以该插件应该可以解决问题。在过多担心用户登录之前,我需要进行更多的导入运行。

还有一个问题。有没有办法重置系统以允许我进行另一次导入。我开始之前应该备份的,但忘了 :anguished:

哦。你的意思是只是设置好 MySQL。我明白了。

如果你懂其他语言,你大概也能应付。
在我学习 Ruby 之前,我写了好几个导入器。:slight_smile:

这里有一个删除并创建新 Discourse 数据库的方法。

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

如果你能记得备份,可能会快一点。也许吧。

另一个技巧是,一旦你处理好了用户,可以在导入用户后停止脚本,然后进行备份。这样你就可以调试帖子导入,而不必再次导入所有用户。

我懂一些。我早在1976年就用Intel 4004的二进制机器码写了我的第一个程序。我正在通过DuckDuckGo来理解一些对我来说是新的代码结构,smf2.rb 正在变得有意义。

感谢数据库的删除/创建方法。是时候重新开始,看看我是否能对导入器进行一些渐进式更改以适应我的数据。

1 个赞

我已经设法修改了导入器,为已删除的用户创建了带有虚假电子邮件地址的虚拟帐户,并且虚拟帐户拥有其正确的帖子,所以这是一个好的开始。

接下来我试图理解附件,因为在我迄今为止导入的所有帖子中都没有看到附件(应该有一些)。

如果我通过 Discourse 网页正常创建一条消息,我会在 posts 表中得到一条记录(id=4346),在 uploads 表中得到两条记录(ids=403 和 404),在 upload_references 中得到四条记录(403/Draft/4、403/Post/4346、404/Draft/4、404/Post/4346)。我还看到 post 4346 的 image_upload_id 字段中有 403,并且 posts/cooked 字段中有引用这两个上传的 HTML。

对于导入的帖子,我为每个导入的 SMF 消息获得一个 post 表记录,并为每个与导入的 SMF 消息关联的附件获得一个 uploads 表记录。uploads 表记录引用包含正确图像的磁盘文件,所以这部分工作正常。但是,我没有为上传的图像获得任何 upload_references 记录,也没有在 posts 表的 image_upload_id 字段中获得任何 upload id。

我假设我需要尝试创建 upload_references 记录并填充 posts-image_upload_id 和 cooked 字段,但我想先确认一下导入器是否没有使用(或试图使用)其他将上传与帖子关联的方法?

听起来你需要将引用添加到 raw 中。有一个函数可以为你生成链接。我不记得它叫什么了。我认为它在 uploads 模型中,但如果你不知道什么是模型,那么在其他导入脚本中可能更容易找到它。

我正在调整导入脚本以适应论坛的特殊性,但在几天前遇到了一个障碍。在 Discourse beta 的最新更新后,我无法再构建导入容器。我收到了…

> FAILED
> --------------------
> Pups::ExecError: cd /var/www/discourse && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libmariadb-dev failed with return #<Process::Status: pid 439 exit 100>
> Location of failure: /usr/local/lib/ruby/gems/3.1.0/gems/pups-1.1.1/lib/pups/exec_command.rb:117:in `spawn'
> exec failed with the params {"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 failed with exit code 100
> ** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.

我已经看到了关于 yarn 密钥过期的帖子,并已修复。这曾阻止安装 libmariadb-dev 包,但我手动安装了该包,并且工作正常。即使在手动安装 MariaDB 包后,使用 mysql 导入模板重新构建导入仍然不起作用。

我构建了一个新服务器,并从头开始安装了 Discourse,以避免与之前的服务器/安装相关的任何潜在问题。但新服务器出现了与旧服务器相同的错误。

我不知道接下来该尝试什么,所以欢迎任何建议!

请参阅 Apt-get update fails inside container yarn repo not signed - #5 by pfaffman mysql 模板。

1 个赞

感谢您指明了正确的方向。我现在知道我哪里做错了!

1 个赞

我们开始迁移 SMF 2(精确地说是 v2.0.15)论坛的测试,遇到的第一个问题之一是当类别名称中包含“与号”时出现的问题:

标题中包含“与号”的主题似乎没问题:
image

到目前为止,“与号”似乎是唯一有问题字符,例如德语的变音符号都没问题:

我们可能也遇到了在此帖子中报告的问题(已删除用户、附件、论坛内的链接),但导入仍在进行中,完成后我会更新。

在这方面,我想知道导入速度是否真的应该这么慢。我们目前在一台配备 64GB RAM 的 AMD Ryzen 5 3600 机器(Hetzner,Ubuntu 22.04)上以 1750 个项目/分钟的速度导入(最初接近 2000 个项目/分钟),这使得整个迁移大约需要 3 天。

速度相当不错。

我想象中报告的问题仍然存在,尽管令人惊讶的是,许多问题是论坛特有的。如果您想修复一些东西并且有预算,我很乐意提供帮助。

1 个赞

谢谢!一旦事情变得更具体,我会回复你。

现在我们(一个以桌面角色扮演游戏及相关爱好为中心的小型非营利组织)正处于评估阶段——大家一致认为我们需要新的软件,而 Discourse 是目前最受欢迎的选择。但我们必须收集所有待办事项(迁移、新主题、需要时的新插件/主题组件),看看是否能将所有内容都纳入我们的预算。

1 个赞

此步骤有特殊原因吗?

据我仔细重读 OP 所见,该 smf2.rb 文件未被更改/修补?

并且,如果 smf2.rb 位于主机上的(例如)/var/discourse/smf2 中,并且您已在步骤 2 中相应地设置了卷挂载,那么它无论如何都会被挂载到客户机内部的 /shared/smf2。

我不明白将其作为单独步骤复制进去的必要性。但理解这一点可能是弄清楚为什么 95% 的附件无法被脚本正确找到的关键……

1 个赞

听起来你对(无需)复制它这个说法是正确的。也许作者更改了它,而他们的更改随后被合并到了核心中。

如果你能获得 5% 而不是 0% 的附件,那么脚本就出错了。

在某些系统中,有两种方法可以附加文件:一种是通过在文件中提及它(这样它就在帖子的原始文本中,并以这种方式处理),另一种是通过在某些元数据/表中将其附加到帖子。我猜你的数据库中有 95% 是用一种方式完成的,而脚本使用的是另一种方式。

但它看起来好像在尝试两种方式?你需要找到一个应该有附件的帖子,在数据库和文件系统中查看它是如何存储的,然后查看代码,找出它为什么获取不到。

1 个赞

谢谢 @pfaffman,这让我很放心!我有点认为情况就是这样,但由于我在这次导入中遇到了很多问题,我一直在怀疑自己各方面的知识和技能!

感谢您的建议,一切都值得感激 @pfaffman - 这是我去年在同一个论坛上工作的延迟了很久的重新尝试。这是一项义务工作,但如果到时候您有时间,我可能会再次请您帮忙。

这是一个非常老的 SMF2 论坛,它有两种形式的附件:

  • id_文件名_无区分大小写_规则_jpg_32字符可能MD5哈希值0fsom4thing
  • id_40字符可能SHA1哈希值0fsom4thing

我仍在努力弄清楚失败是否有规律。

我的猜测(不看代码!)是其中一个脚本执行的操作,而另一个不是(可能一种是旧方法,所以新帖子使用另一种方法,但它没有回溯修复那些使用旧方法的内容)。

所以看看 convert_message_body 和附件表中的字段。也许他们因为某些原因从 MD5 切换到了 SHA1,或者反之亦然。

就像我说的,可能是这些版本中的一个引用了上传文件,而不是将其链接在表中,所以你会执行一个 gsub 来查找该模式,然后如果匹配成功,你就会获取键,在表中查找它,然后用该文件执行 create_upload

希望这足以让你开始,但如果你需要我在这里无法提供的更多帮助,请联系我。