用 Webmention 接收 Mastodon 互动

什么是 webmention #

Webmention是由IndieWeb发起的W3C标准,用来实现网页间相互提及,不必借助平台或引入评论系统。它的工作流程如下:

  1. 我上传了一篇文章
  2. 文章被你引用
  3. 你向我的网站发送带有引用处url的webmention
  4. 我通过webmention.io等服务或自行挂载,接收到你的webmention

现在你就可以试试,在自己的页面提及此页url,例如:

<p><a href="https://fanrongbin.com/hugo-webmention-bridgy-mastodon">I'm trying webmention!</a></p>

然后把你的页面url在文末输入框提交,大约一分钟后刷新此页,就会看到你的webmention。

接收 webmention #

这里给出使用webmention.io的步骤,你也可以自行挂载:

1. 用 IndieAuth 标识你的身份 #

Webmention.io使用IndieAuth登录,所以需要先设置IndieAuth。在index.html中,对自己的帐号说明为rel="me",例如:

<a rel="me" href="mailto:your_email@email.com">Send me an email</a>

或者以隐藏的方式在<head>说明:

<link rel="me" href="mailto:your_email@email.com">

这样一来,采用IndieAuth登录的地方,会通过这些方式验证你的身份,例如向邮箱发送邮件,或跳转Github登录。

2. 使用 webmention.io 挂载 #

在webmention.io登录后,你会看到一个Settings-Setup页面,给出了需要你在<head>加入的tag:

<link rel="webmention" href="https://webmention.io/your_domain/webmention" />

这条tag说明你的页面能够接受别人的提及,你可以通过webmention.rocks测试能否接收到。

到此,你已经实现了webmention的接收。

你可以在webmention.io的Dashboard,或它提供的Mentions Feed,查看他人提及。

3. 借助 webmention.js 在博文页面显示 webmention #

Webmention.io提供API返回你接受到的具体内容,这里我们借助前人造好的轮子webmention.js,根据readme,在你的网站存放webmention.min.js文件并用<script src=""></script>引入,在需要展示webmention列表的地方插入:

<div id="webmentions"></div>

你可以新建一个测试页面,用来提及目标页,以测试是否能正常发出和显示。也可以在连接Mastodon后,通过发toot和回复的方式测试。webmention列表的样式可通过css自定义。

发送 webmention #

很多支持webmention的站点,都会给出一个form方便你手动提交自己的链接。

你也可以用curl发出webmention,发送前需检查对方收不收得到webmention,下面这条指令会进行检查。$your_url替换为你自己的引用页,$target_url替换为目标页。

curl -i -d "source=$your_url&target=$target_url" `curl -i -s $target_url | grep 'rel="http://webmention.org/"' | sed 's/rel="webmention"//' | grep -o -E 'https?://[^ ">]+' | sort | uniq`

也可以用telegraph.p3k.io(需要IndieAuth登录),或mention.tech(不需要登录)的在线服务。

使用 webmention.app 自动发送 #

你可能一次在博文中引用多个网页,但是不想再进行繁琐的手动发送webmention。Webmention.app可以读取页面class="h-entry"中的链接,帮你一键发送。

可以使用Test页面检查(只会检查前10个h-entry),也可以通过API。登录服务获得token后没有request限制。具体请参见官网。

将你的博文发送到社交平台 #

连接到 Bridgy #

Bridgy可将网站和社交平台相联,使得没有个人页面的用户,也能通过支持的平台进行回复,Bridgy会帮助进行webmention。

进入主页选择Mastodon,使用cross-post或直接连接联邦宇宙的方式均可。如果cross-post,你需要用验证过的帐号publish带有博文链接的toot,在这条toot下的回复、转发、喜爱才会作为webmention传过来。

如果直接连接(也就是我目前的做法),你会以@your-domain.com@your-domain.com加入联邦宇宙,向Bridgy的每次update都会对应更新这个账号下的toot。

使用 Github Actions 自动化 #

我使用Hugo作为博客系统,希望实现根据我是否上传或更新.md,自动发出webmention。tj-actions/changed-files能够找到repo下文件的修改情况,故可以先寻找是否有文件被修改,之后发出 curl命令即可。

之前的博文里,我设置了deploy.yml用来自动部署Hugo、生成静态文件。故对应在此设置为在deploy后才运行。

name: send webmentions to bridgy according to md changes

on:
  workflow_run:
    workflows: ["deploy"]
    types: 
      - completed
    branches:
      - main

jobs:
  changed_files_send_webmention:
    runs-on: ubuntu-latest
    name: send webmentions according to md changes
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: get changed files
        id: changed-files
        uses: tj-actions/changed-files@v41
        with:
          files: content/posts/*.md # 注意这里根据实际需要修改目录位置

      - name: list all changed files
        run: |
          ALL_CHANGED_FILES="${{ steps.changed-files.outputs.all_changed_files }}"
          for file in $ALL_CHANGED_FILES; do
            echo "$file was changed"
          done          

      - name: send webmentions
        if: steps.changed-files.outputs.all_changed_files != '' # 判断不为空才运行
        run: |
          CHANGED_FILES=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ',' '\n')
          for FILE in $CHANGED_FILES; do
            if [[ $FILE == content/posts/*.md ]]; then
              POST_NAME=$(basename "$FILE" .md)
              POST_URL="https://your-domain.com/${POST_NAME}"
              echo "Sending Webmention for $POST_URL"
              curl -i -d source=${POST_URL} -d target=https://fed.brid.gy https://fed.brid.gy/webmention
            fi
          done          

你还可以接着使用${POST_URL}trigger webmention.app的webhook。


最初是看到IndieWeb上关于webmention的介绍,于是想着要不要自己也折腾一下,搜索到Aaron Parecki的博文,以及Jayeless.net的博文后,觉得配置起来也不是很难嘛,然后就开始了……用第三方服务接收很简单,主要是一直卡在Bridgy这边。我新建了一个Stream页面,相当于有了自己的一条时间轴,为了传上联邦宇宙,需要把每条小note以锚点#id的方式传到Bridgy。但,用webmention.app或者是telegraph.p3k.io始终没法发现到https://fed.brid.gy/这条链接,导致我没法API传出去,后来:

  1. 尝试以<a href="https://fed.brid.gy" hidden="from-humans"></a>的方式,加到带class="e-content"的元素里面。但如果note不包含其他url,具有Link Preview功能的地方,还是会显示出fed.brid.gy的链接卡片。
  2. 在对Stream页面部署自动化时,分成了三个部分:
    • 固定以url#id作为source并以Bridgy作为target、
    • 检查这条note的类型并以相关url作为target(例如reply、like)
    • 检查这条note的内容并以相关url作为target(里面所有的<a href="..."

一些遗留的问题 #

  1. 如果fediverse上对博文的回应(回复、转发、喜爱)被修改或删除,无法触发Bridgy自动更新,即以回应为source,以博文为target重新发一次webmention
  2. 如果发出回应的用户更改了自己的个人信息,也无法触发Bridgy自动更新,这个应该更没法解决了。

Respond on Mastodon, webmention this post, or contact me directly.

You can use Hypothes.is to select texts and highlight.

You've copied this page url!

Search it in your Mastodon server, and reply that toot by @fanrongbin.com@fanrongbin.com.