ActivityPub 插件

|||
-|-|-|
:discourse2: | 摘要 | Discourse ActivityPub 允许您通过 ActivityPub 发布 Discourse 帖子,以便在支持 ActivityPub 的服务(如 Mastodon)上阅读。
:hammer_and_wrench: | 代码库链接 | GitHub - discourse/discourse-activity-pub: Adds ActivityPub support to Discourse.
:open_book: | 安装指南 | 如何在 Discourse 中安装插件

如果您不熟悉 ActivityPub,请先观看此短视频:

准备好开始设置插件后,请查看我们的 activitypub Documentation > Integrations 主题:

65 个赞

感谢您的辛勤工作!我非常期待启用此功能,并感谢您发布此测试版本,以便我们这些拥有各种设置的用户能够为更广泛的场景提供测试支持。

在考虑何时为我的网站启用此功能时,我正在思考可能存在的“单向门”。

子类别

我有 8 个顶级类别,此外还有 21 个公共子类别。需要关注 29 个参与者才能关注所有公共网站活动,这似乎有点多。此外,用户可能会惊讶地发现,关注一个类别并不包括关注其子类别。

如果我能在类别 ActivityPub 设置中选择“也联合发布公共子类别”选项,我会这样做的。从用户的角度来看,单独联合发布子类别似乎主要是一个单向门。因此,如果您能考虑一个“也联合发布子类别”的选项,这可能会影响我的计划。我们的默认侧边栏仅显示顶级类别,而 Discourse 在查看它们时的默认设置是所有顶级和子类别内容一起显示,这似乎与 Discourse 的预期相当一致。

联合发布所有内容!

我认为,为联合发布网站上所有公共帖子的 ActivityPub 参与者添加一个全站范围的设置可能会很有趣。我自己也会使用它。但我不认为这是一个单向门——一旦类别联合发布功能准备就绪,我就会立即设置它,即使我以后会添加一个“all@”参与者来联合发布所有内容。

编辑限制

您的帖子中不明显的一点是,可以理解为只有字面上的 [note]...[/note] 部分无法编辑。对于这里的其他人来说,它真正的意思是,一旦帖子被联合发布,编辑将暂时禁用所有帖子(除了那些包含字面 [note]...[/note] 部分的帖子);只有当您尝试保存您的编辑时,才会显示此消息:

我的网站有意允许足够受信任的用户无限期编辑,因此在无法禁用此控件(或因联合发布编辑而移除控件)的情况下,我无法启用此功能。作为一个适用于信任网站之外的通用示例,任何具有 wiki 模式帖子的类别都会因设置该类别的联合发布而损坏。

我尝试删除一个我设为 wiki 的已联合发布的帖子,然后看到了这个:

但是,该帖子已被删除,并且删除操作已联合发布。

个性化

为每个指定的参与者提供一个头像会很好。在 Mastodon 中,我只能看到每个类别参与者的灰色大象图片,我很想在这里添加一点个性。:smiling_face:

错误日志

到目前为止,我在日志中从 activitypub 插件中收到了两种类型的错误:

Message (3 copies reported)

NoMethodError (undefined method `ap_type' for nil:NilClass)
(eval):7:in `_fast_attributes'
app/controllers/application_controller.rb:418:in `block in with_resolved_locale'
app/controllers/application_controller.rb:418:in `with_resolved_locale'
lib/middleware/omniauth_bypass_middleware.rb:74:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/anonymous_cache.rb:367:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
lib/middleware/enforce_hostname.rb:24:in `call'
lib/middleware/request_tracker.rb:228:in `call'

Backtrace

plugins/discourse-activity-pub/lib/discourse_activity_pub/ap/activity.rb:18:in `object'
plugins/discourse-activity-pub/app/serializers/discourse_activity_pub/ap/activity_serializer.rb:18:in `_object'
plugins/discourse-activity-pub/app/serializers/discourse_activity_pub/ap/activity_serializer.rb:9:in `attributes'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:480:in `_serializable_hash'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:359:in `serializable_hash'
active_model_serializers (0.8.4) lib/active_model/serializer.rb:347:in `as_json'
plugins/discourse-activity-pub/lib/discourse_activity_pub/ap/object.rb:50:in `json'
plugins/discourse-activity-pub/app/serializers/discourse_activity_pub/ap/collection/ordered_collection_serializer.rb:7:in `map'
plugins/discourse-activity-pub/app/serializers/discourse_activity_pub/ap/collection/ordered_collection_serializer.rb:7:in `ordered_items'
(eval):7:in `_fast_attributes'
Message

Job exception: undefined method `model' for #<DiscourseActivityPubActivity id: 2, ap_id: "https://social.makerforums.info/cf2e1e8d-83e3-447e...", ap_key: nil, ap_type: "Follow", local: nil, actor_id: 3, object_id: "1", object_type: "DiscourseActivityPubActor", summary: nil, published_at: nil, created_at: "2023-06-01 02:23:13.798564000 +0000", updated_at: "2023-06-01 02:23:13.798564000 +0000">


Backtrace

/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activemodel-7.0.4.3/lib/active_model/attribute_methods.rb:458:in `method_missing'
/var/www/discourse/plugins/discourse-activity-pub/app/models/discourse_activity_pub_activity.rb:79:in `after_deliver'
/var/www/discourse/plugins/discourse-activity-pub/app/jobs/discourse_activity_pub_deliver.rb:42:in `perform_request'
/var/www/discourse/plugins/discourse-activity-pub/app/jobs/discourse_activity_pub_deliver.rb:13:in `execute'
/var/www/discourse/app/jobs/base.rb:249:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rails_multisite-5.0.0/lib/rails_multisite/connection_management.rb:82:in `with_connection'
/var/www/discourse/app/jobs/base.rb:236:in `block in perform'
/var/www/discourse/app/jobs/base.rb:232:in `each'
/var/www/discourse/app/jobs/base.rb:232:in `perform'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/sidekiq-6.5.9/lib/sidekiq/processor.rb:202:in `execute_job'

再次感谢您的工作!

8 个赞

我很高兴地说 SocialHub 已经在运行了:

…点击,点击,点击…

它现在应该已经出现在 Fediverse 上了… 正在查看日志…

哦,在第一次尝试关注一个 Actor时出现了问题:

  • Job exception: undefined method model’ for #\u003cDiscourseActivityPubActivity id: 2, ap_id: "https://ps.s10y.eu/820e6bf2-ec02-49f8-ab5e-e3cefbb…", ap_key: nil, ap_type: "Follow", local: nil, actor_id: 4, object_id: "2", object_type: "DiscourseActivityPubActor", summary: nil, published_at: nil, created_at: "2023-06-01 13:30:16.131136000 +0000", updated_at: "2023-06-01 13:30:16.131136000 +0000"\u003e`
  • Job exception: undefined method model’ for #\u003cDiscourseActivityPubActivity id: 8, ap_id: "https://mastodon.social/ce62fd77-fe03-4060-a951-79…", ap_key: nil, ap_type: "Follow", local: nil, actor_id: 8, object_id: "2", object_type: "DiscourseActivityPubActor", summary: nil, published_at: nil, created_at: "2023-06-01 13:39:14.512966000 +0000", updated_at: "2023-06-01 13:39:14.512966000 +0000"\u003e`
  • Job exception: undefined method model’ for #\u003cDiscourseActivityPubActivity id: 6, ap_id: "https://social.coop/4236c87a-0d22-402d-8546-e37a21…", ap_key: nil, ap_type: "Follow", local: nil, actor_id: 6, object_id: "2", object_type: "DiscourseActivityPubActor", summary: nil, published_at: nil, created_at: "2023-06-01 13:38:54.493118000 +0000", updated_at: "2023-06-01 13:38:54.493118000 +0000"\u003e`
这是最后一个的堆栈跟踪
activemodel-7.0.4.3/lib/active_model/attribute_methods.rb:458:in `method_missing'

/var/www/discourse/plugins/discourse-activity-pub/app/models/discourse_activity_pub_activity.rb:79:in `after_deliver'

/var/www/discourse/plugins/discourse-activity-pub/app/jobs/discourse_activity_pub_deliver.rb:42:in `perform_request'

/var/www/discourse/plugins/discourse-activity-pub/app/jobs/discourse_activity_pub_deliver.rb:13:in `execute'

/var/www/discourse/app/jobs/base.rb:249:in `block (2 levels) in perform'

rails_multisite-5.0.0/lib/rails_multisite/connection_management.rb:82:in `with_connection'
/var/www/discourse/app/jobs/base.rb:236:in `block in perform'

/var/www/discourse/app/jobs/base.rb:232:in `each'

/var/www/discourse/app/jobs/base.rb:232:in `perform'

sidekiq-6.5.9/lib/sidekiq/processor.rb:202:in `execute_job'

sidekiq-6.5.9/lib/sidekiq/processor.rb:170:in `block (2 levels) in process'

sidekiq-6.5.9/lib/sidekiq/middleware/chain.rb:177:in `block in invoke'

/var/www/discourse/lib/sidekiq/pausable.rb:134:in `call'

sidekiq-6.5.9/lib/sidekiq/middleware/chain.rb:179:in `block in invoke'

sidekiq-6.5.9/lib/sidekiq/middleware/chain.rb:182:in `invoke'

sidekiq-6.5.9/lib/sidekiq/processor.rb:169:in `block in process'

sidekiq-6.5.9/lib/sidekiq/processor.rb:136:in `block (6 levels) in dispatch'

sidekiq-6.5.9/lib/sidekiq/job_retry.rb:113:in `local'

sidekiq-6.5.9/lib/sidekiq/processor.rb:135:in `block (5 levels) in dispatch'

sidekiq-6.5.9/lib/sidekiq.rb:44:in `block in <module:Sidekiq>'

sidekiq-6.5.9/lib/sidekiq/processor.rb:131:in `block (4 levels) in dispatch'

sidekiq-6.5.9/lib/sidekiq/processor.rb:263:in `stats'

sidekiq-6.5.9/lib/sidekiq/processor.rb:126:in `block (3 levels) in dispatch'

sidekiq-6.5.9/lib/sidekiq/job_logger.rb:13:in `call'

sidekiq-6.5.9/lib/sidekiq/processor.rb:125:in `block (2 levels) in dispatch'

sidekiq-6.5.9/lib/sidekiq/job_retry.rb:80:in `global'

sidekiq-6.5.9/lib/sidekiq/processor.rb:124:in `block in dispatch'

sidekiq-6.5.9/lib/sidekiq/job_logger.rb:39:in `prepare'

sidekiq-6.5.9/lib/sidekiq/processor.rb:123:in `dispatch'

sidekiq-6.5.9/lib/sidekiq/processor.rb:168:in `process'

sidekiq-6.5.9/lib/sidekiq/processor.rb:78:in `process_one'

sidekiq-6.5.9/lib/sidekiq/processor.rb:68:in `run'

sidekiq-6.5.9/lib/sidekiq/component.rb:8:in `watchdog'

sidekiq-6.5.9/lib/sidekiq/component.rb:17:in `block in safe_thread'

我的 Feed 里似乎没有出现这个 Note :frowning:

(欢迎将此消息移至更合适的位置)

8 个赞

从长远来看,我同意,这应该是每个参与者特定的并且可配置的。但目前,站点徽标_应该_会被拾取。它对我来说可以用于 @feature@meta.discourse.org

4 个赞

好的,这可能与我看到的其中一个错误有关。站点 logo 对我来说很有意义。

仔细想想……如果有可能在那里使用分类颜色,那就太棒了,但我不知道是否有合适的位置。

4 个赞

我重试了,结果……

部分有效:笔记比原来的缩短得太多了(71 个字符):

我们一直在等待它:现在,感谢 Angus McLeod 和 pavilion 团队,以及 #Discourse 背后的公司 CDCK, Inc.,#SocialHub 现在已实现联合!您可以关注 @fediverse@socialhub.activitypub.rocks 获取一般公告,关注 @feps@socialhub.activitypub.rocks 获取 Fediverse 增强提案。
:hugs:

4 个赞

通用建议:

在启用 ActivityPub 集成之前,请考虑几天。

请记住,这些帐户将在社交网络联合宇宙中永远列出,如果您事后意识到帐户/类别名称需要更改,可能会造成混淆。 :heart:

2 个赞

我相信,从长远来看,还可以实现账户移动,以便为某个类别重命名参与者。这只是需要有人愿意付出努力才能完成的额外工作,所以我怀疑这会是短期内能实现的事情。:smiling_face: 至少,我希望它能晚于其他更有价值的工作出现!:grin:

这完全不会否定你的观点。

3 个赞

感谢大家的反馈 :slight_smile:

@hellekin 这将解决您报告的异常。@mcdanlj 这也将解决您报告的第二个异常(相同的问题)。

@mcdanlj 您报告的第一个问题有点奇怪,您看到它的频率有多高?您能提供更多细节吗?

感谢您对此的反馈,在第二阶段的工作中一定会考虑 :+1:

我认为这可能不会在第二阶段实现,但已记录 :+1:

编辑仅在构成笔记内容的帖子中被禁用。如果您不使用笔记标签,那就是前 500 个字符,或者您设置的 activity pub note excerpt maxlength 的值。我肯定会在第二阶段考虑的一件事是要求使用 [note][/note] 标签来分隔笔记,因为我可以看到这会引起混淆。

您可以通过使用 [note][/note] 标签将笔记与其他内容分开来解决此问题。

知道了!我们没有明确测试过维基帖子。到目前为止,我还没有能够重现您删除维基帖子的错误。您能可靠地重现它吗?我在此 PR 中添加了一些测试用例,所有这些测试用例在该场景下都通过了,但我想彻底解决这个问题。

摘录解析目前由 Discourse 中用于主题摘录解析的相同系统处理(用于主题列表的目的),这可能是它删除了大部分内容的原因(主题列表摘录也会如此)。我认为我们可能需要使用单独的解析器,因为我预见到这会造成一些问题。请耐心等待,这将在第二阶段解决。

请记住,您可以随意更改显示名称,并且更改用户名的限制并非此插件独有。所以,虽然您说的是事实,但 fediverse 的很大一部分也是如此。

此外,我没有将用户名包含在参与者的 id 中,部分是为了将来能够添加更改用户名的功能。

该插件的 ActivityPub 数据与 Discourse 的数据是分离的。更改参与者关联的 Discourse 模型(即类别)没有固定的限制。您甚至可能在未来将参与者与不同类型的 Discourse 模型相关联,例如,将您为类别创建的参与者与用户相关联(参与者与 Discourse 模型之间的关系是多态的)。我并不是说这些将明确添加为功能,而是说在这方面没有硬性限制。

总的来说,是的,考虑哪些类别要作为参与者是值得的,但总体而言,此实现的灵活性相对较高,因此您的担忧程度应相对于该背景。我在这里更详细地解释了该插件中数据流的性质,这进一步阐明了这一点

再次感谢大家!很高兴有积极的用户。

5 个赞

我认为这与删除帖子有关,因为我删除了三个测试帖子,出现了三次错误。

这对我的网站来说绝对是无法使用的。我不想把 Discourse 用作比直接在 Mastodon 上发帖更麻烦的方式来撰写 fediverse 帖子。强迫我的整个社区开始使用 [note]...[/note] bbcode 注释,包括经常寻求帮助的新网站用户,这是不可行的。

不,我绝对不能。这不是关于我。这是关于我的网站用户,他们是 Discourse 用户,而不是 discourse/discourse-activity-pub.git 用户。

这只是一个编辑。

编辑的联合是正常的。据我所知,目前市面上大多数广泛使用的 ActivityPub 实现很早就支持编辑了。Mastodon 是在去年才屈服并允许编辑的,在流行的实现中是最后的。

我认识到编辑不是 MVP 版本的一部分,但除非它要么联合编辑,要么给我关闭笔记不可编辑的选项,否则我无法为我的网站启用它。当然,我不知道我的用例是奇怪的还是正常的。

我自己的目标是使用 ActivityPub 插件,让我的社区论坛成员更容易地关注和分享他们使用 Discourse 创建的内容。而不是将 Discourse 用作一个奇怪的、不可编辑的、仅限帖子的 Mastodon 替代品。:smiling_face:

我的理解是,你最终确实打算支持联合编辑,因为错误消息说“目前不支持”——对吗?如果是这样,那么这都只是一个暂时的限制,我们的用例差异并不重要。但这确实让我思考是投入精力保护编辑还是支持联合编辑。

我忘记从我的沙盒站点中删除 retort 插件了,当时我已从我的生产站点中删除了它。删除 retort 修复了奇怪的错误日志和奇怪的错误消息。我的错!

这意味着根据插件目前的运行方式,我们可以为多个类别使用相同的 actor 吗?还是数据模型非常灵活,实现细节易于更改?

就我而言,在我的用例中,我更希望发布整个内容而不做任何限制。我知道其他人可能不会这样配置,但我认为最终我会将最大大小设置为与我的 Discourse 上的帖子最大大小相同,那就是……很大!:smiling_face:

2 个赞

明白了,我很快会进一步调查。

明白了。我的评论更多的是指,在发布后编辑非笔记内容确实是可能的。你说得对,这个初始版本对于普通用户来说,在用户体验方面会有一些问题。不过,它确实在其他方面支持得很好,例如联合公告。

是的,我们将在第二阶段添加对发布后编辑笔记内容的支持。请注意,在笔记发布之前,目前是支持编辑的。当你构建这样的东西时,你必须尽可能减少移动的部件。

还没有。你能在这里更详细地解释一下你的意思吗?你是想有一个全站 actor,还是更倾向于子类别问题?

是的,尽管我不会特别使用“容易”这个词 :wink:

我很好奇你打算将不受限制的内容联合到哪里?这是个真实的问题;我想更深入地了解你的想法。

2 个赞

我忘了在发现错误是由于意外保留了 retort 而在事后编辑掉。 :flushed:

哎呀。

够好了! :pray:

我不再担心这个问题了,在第二阶段我会帮忙测试。

我隐约想过两者,但这只是一个低价值的问题。我只是好奇我的暂存网站的实验能走多远,并且不想尝试那些已知不可能的事情。 :+1:

我会试试!

背景:Mastodon 限制了用户撰写帖子的长度,但显示帖子的长度不受限制。我运行了一个配置了 2000 个字符限制的 Mastodon-glitch 服务器;我看到几个人发帖说配置了 31337 个字符的限制(因为当然)。我在信息流中看到来自使用 pleroma、akkoma 等工具的人的长帖子。

我认为,我的 Discourse(Maker Forums)上不时会出现一些非常酷的内容,我想在 Fediverse 上推广它,以便更广泛的受众能够访问。我知道 Mastodon 一直认为 500 个字符是微博客的理想长度——但 ActivityPub 不仅限于微博客。它是联合,包括但不限于微博客。当我在我的 Mastodon 账户中关注一个 ActivityPub 参与者时,它并不局限于短帖子。我可以阅读、评论和转发更长的帖子。

所以“您预计会将内容联合到哪里”对我来说是个令人困惑的问题。

  • 我会从我的 Mastodon-glitch 服务器转发内容。转发不应用字符限制,即使在标准的 Mastodon 上,该限制也适用于撰写帖子。
  • 我预计社区成员会从任何 ActivityPub 服务器关注(认识到目前这更多是 Mastodon),而且他们不会都对 ActivityPub 笔记应该有多长有相同的看法。

最终,作为服务器管理员,我无法控制内容被联合到哪里。这是每个关注者的决定。我不明白为什么即使是 Mastodon 上的关注者,将整个 Discourse 帖子作为 ActivityPub 笔记排除或联合会有所不同,尤其是在整个 Fediverse 中。

我不确定这是否回答了您的问题。但我也不能很好地理解它。 :grin: 如果您愿意,我很乐意深入探讨这个问题。

2 个赞

没关系!很高兴我们目前已经处理了异常。如果您发现任何其他问题,请告知我们。@hellekin 同样,如果您发现任何其他问题或奇怪的行为,也请告知我们。

太好了!谢谢您。

回答了!谢谢您,这为我们规划第二阶段提供了有用的背景信息。

5 个赞

我即将升级到最新版本。有一点会很有用,那就是可以选择受众:帖子是公开的还是仅限关注者。现在是后者,所以我们不能推广它,并且必须在收到通知之前关注该帐户。我很欣赏这一点,因为它仍然是实验性的,但绝对应该有一个公开帖子的选项,以便我们可以更广泛地向 Fedizens 宣传该功能 :slight_smile:

5 个赞

是的,这是我们将在第二阶段考虑的事情 :+1:

6 个赞

您有开发阶段的公开路线图吗?

3 个赞

目前没有公开的路线图,但一旦我们确定了具体细节,我会通知你。欢迎提出任何合理的建议!像 @mcdanlj 这样的具体用例示例也总是有帮助的。

6 个赞

我在 SocialHub 上提出了一些建议,这些建议很久以前在这里也提出过……

2 个赞

我在从暂存服务器进行的测试中还没有注意到这一点,但我也想承认推广是我自己用例的核心。

6 个赞

处理 410 Gone

我的日志中有很多(已更改 URL):

[Discourse Activity Pub] GET 请求到 https://activitypub.example/users/missing-account 失败:Expected([200, 201, 202, 301, 302, 307, 308]) <=> Actual(410 Gone)

我相信这与以下内容有关:如果响应正文中包含 Tombstone,则对象检索应响应 410 Gone 状态码,否则响应 404 Not Found(server:object-retrieval:deleted-object:410-status):帐户已迁移到另一个实例。


还收到一些:



[Discourse Activity Pub] update_stored_from_json 保存 actor 失败。AR 错误:Ap 已存在。Actor JSON:{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","toot":"http://joinmastodon.org/ns#","featured":{"@id":"toot:featured","@type":"@id"},"featuredTags":{"@id":"toot:featuredTags","@type":"@id"},"alsoKnownAs":{"@id":"as:alsoKnownAs","@type":"@id"},"movedTo":{"@id":"as:movedTo","@type":"@id"},"schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value","discoverable":"toot:discoverable","Device":"toot:Device","Ed25519Signature":"toot:Ed25519Signature","Ed25519Key":"toot:Ed25519Key","Curve25519Key":"toot:Curve25519Key","EncryptedMessage":"toot:EncryptedMessage","publicKeyBase64":"toot:publicKeyBase64","deviceId":"toot:deviceId","claim":{"@type":"@id","@id":"toot:claim"},"fingerprintKey":{"@type":"@id","@id":"toot:fingerprintKey"},"identityKey":{"@type":"@id","@id":"toot:identityKey"},"devices":{"@type":"@id","@id":"toot:devices"},"messageFranking":"toot:messageFranking","messageType":"toot:messageType","cipherText":"toot:cipherText","suspended":"toot:suspended"}],"id":"https://mas.to/users/rikvipcode","type":"Person","following":"https://mas.to/users/rikvipcode/following","followers":"https://mas.to/users/rikvipcode/followers","inbox":"https://mas.to/users/rikvipcode/inbox","outbox":"https://mas.to/users/rikvipcode/outbox","featured":"https://mas.to/users/rikvipcode/collections/featured","featuredTags":"https://mas.to/users/rikvipcode/collections/tags","preferredUsername":"rikvipcode","name":"","summary":"","url":"https://mas.to/@rikvipcode","manuallyApprovesFollowers":false,"discoverable":false,"published":"2023-05-04T00:00:00Z","devices":"https://mas.to/users/rikvipcode/collections/devices","suspended":true,"publicKey":{"id":"https://mas.to/users/rikvipcode#main-key","owner":"https://mas.to/users/rikvipcode","publicKeyPem":"--...


还有

[Discourse Activity Pub] GET 请求到 https://mastodon.social/users/ejovoni46709 失败:Expected([200, 201, 202, 301, 302, 307, 308]) <=> Actual(410 Gone)
[Discourse Activity Pub] Failed to process https://mastodon.social/users/ejovoni46709: Could not resolve actor
[Discourse Activity Pub] Failed to process https://mastodon.social/users/ejovoni46709#delete: Could not create actor
[Discourse Activity Pub] Failed to process https://mastodon.social/users/epybisezax9438#delete: Could not find object
3 个赞