My avatar

北雁云依的博客

My avatar

北雁云依的博客

决不跪在地上
以显出刽子手们的高大
好阻挡自由的风

RSS
· 浏览

更换博客的ActivityPub实现

我的博客早就有了ActivityPub支持,当时还是手工编程时代,我照着已有的教程和wildebeest做的。在几天又痛又快乐的开发以后,我摘下了几颗低垂的果实:在联邦宇宙里搜索本文链接,就能找到文章的标题和摘要,点击作者头像就能找到这个博客对应的账号(Actor),关注它,就能订阅文章之后的更新。如此这般,我可以发文章,读者能收到推送,还可以评论,我们都有美好的未来。

吧?

让我们看看此前的实现:收件箱只处理了“关注”和“取消关注”这两种请求,如果有用户回复我的帖子,就简单在控制台记个Not Implemented,然后返回成功来骗人。这样一来,用户所在的实例会有这条回复,但其它实例没有,而且我也只能查log。

至于“订阅”,Fediverse是这样要求的:在文章有更新时,需要向所有关注者的Inbox投递特定文章。我的实现是,带Token调用一个接口,接口会把全部文章对着所有订阅者重新发一遍。至于请求失败怎么办、执行到一半挂了怎么办——当然是凉拌了。事已至此,先吃饭吧。

支持ActivityPub真是太简单啦!json-ld极大丰富,能关注,复制文章链接也能搜到,如果再加上真实的评论机制,我的博客就进入了理想中的Fediverse社会。但我的生产力匹配不了更进一步的物质文化需求,于是博客的ActivityPub实现就一直停在了这个初级阶段。

这一等就是两年。这两年里,我溜出了时代银行的后门,在被LLM碾过之前找到了实习和正式岗,还结了婚、逐渐成为了现充。在写其它Side Project时,我找到了一个很好用的命令行参数处理库optique,顺手看了眼作者——怎么是they/them?

对的对的,非二元的,语言学的,自由软件开发者,交叉性女性主义者。这太合我胃口了,毫不犹豫地开始赞助,顺手给他的韩日台港中计算机常用词对照网站交了个issue

又过了半年,他搞出Fedify,彻底解决了TypeScript和Cloudflare Worker接入ActivityPub的问题。我博客的ActivityPub实现终于有救了。


以下内容有LLM的参与。

把协议代码交给Fedify

第一步是把手工拼ActivityStreams对象、处理签名和发送活动的部分换成Fedify,它有自带的词汇库@fedify/vocab

文章和账号都可以直接用它提供的对象来描述,序列化、验签和签名投递也交给Fedify,博客自己负责找文章、存关注者和处理回复。

原来那些从Wildebeest里面抄的websign.js于是被删除了。websign.js是基于WebCrypto API的,但Fedify要求开启Node Compatibility,私以为websign.js是个更好的实现,换掉了多少有点可惜。

actor地址、Note地址和签名密钥都是需要保留的,否则就相当于一个新身份了。迁移过程中Codex也保留了它们。

给评论找个去处

这样以后,账号身份保住了,签名也开始验证了,可以比较放心地接收读者回复——然后继续把它扔掉,因为还没写存储。

现在收到对文章的直接回复,就会检查它确实是作者本人发来的,再存进数据库。重复收到同一条评论也只存一份,编辑和删除同样会更新记录。

不过,消息未必按顺序到达。如果读者先骂了我,想了想又改得温和一点,而旧版本来得更晚,我就会替读者恢复其战斗性。因此,编辑要比较时间,删除也得留下记录,免得迟到的消息让评论复活。读者本来已经决定不骂了,我这边却替其恢复原状,未免有些缺德。

做到这里,评论终于有地方存了。然而读者打开博客,依然看不到联邦回复,因为这次只做了存储,还没有接进页面。现有的Sodesu评论界面照常使用,联邦回复的楼中楼暂且不管,存下来的HTML也得清洗后才能展示。从“没有”进步到了“有,但不给看”,总归也算取得了一些阶段性成果。

发文章,附赠全集

旧的发布接口对“哪些文章已经发过”和“这次发到了哪里”都毫无记忆。前几个人收完了全部文章,后面某个收件箱出了错,整个请求就跟着失败。于是我重新调用接口,前几个人又得从头收一遍——没有共患难,至少可以共收件。

当然,按照ActivityPub的要求,远端应该要根据对象ID去重,但不知为什么订阅者好像就是会收到多份,导致一些实例上会多次出现同一篇文章。

现在改成每五分钟自动检查一次有没有新文章,再通过Cloudflare Queues分批投递、记录进度。Worker中途出些意外,也不用每次都处理已不具现实意义的历史文件。

现在终于不用在一个HTTP请求里等所有人回话了。然而把消息排进队列,并不能顺便把远端服务器修好,对方该掉线还是会掉线,只好等会儿再试。失败任务会隔越来越久重试,次数用完还没成功的,就只能打入冷宫——死信队列,等我排查了。

后记

折腾完以后,博客页面几乎没有变化,联邦评论甚至还没显示出来——需要到任意实例查看。所以,如果只看博客页面,这次改造其实就是——什么都没干。然而至少收到的评论不再直接扔掉,发文章也不用附赠全集了。

分享

复制此页面地址到邦联宇宙搜索框以在邦联宇宙分享本文:https://blog.yunyi.beiyan.us/posts/migrateToFedify

在本站发言,即意味着你同意评论政策(最后更新于2025-06-22)。