💨
Next.jsのSSGで作ってる個人ブログをFediverse対応させてつぶやいてみた
今回は、こちらの記事を参考にさせていただき、自分の作ってるサイトでもFediverse対応してみました。
できたこと
- Next.js(SSG)で作ってるサイト(デプロイ先はVercel)をFediverse対応させて、デプロイ時にBridgy Fed経由でActivityPubで投稿が配信されるようにしてみた
やったこと
Bridgy Fed 対応
↑の参考サイトを見つつ、https://fed.brid.gy/web-site で、自分で持ってるサイトのURLを入れると導入方法を提示してくれます。
/.well-known/host-meta と /.well-known/webfinger を Bridgy Fed にリダイレクトさせる
next.config.jsに以下を追加
next.config.js
const config = {
async redirects() {
return [
{
source: '/.well-known/host-meta',
destination: 'https://fed.brid.gy/.well-known/host-meta',
permanent: false,
},
{
source: '/.well-known/webfinger',
destination: 'https://fed.brid.gy/.well-known/webfinger',
permanent: false,
},
]
}
サイトトップに、h-card 追加
<a
href="https://dl10yr.com/"
className="h-card"
rel="me"
>
dl10yr
</a>
投稿部分にクラスを足していき、micfroformatsのh-entryに対応させる
h-entryで投稿を作成します。
完全には理解していないですが、この辺が参考になりました。
下の例のようにやると、とりあえずMastdonで投稿内容が表示できました。
/app/note/[year]/[month]/[day]/[slug].tsx
export default async function Page({ params }) {
const note = fetchNoteDetailData(params.year, params.month, params.day, params.slug) // mdファイルを取得
return (
<article className="h-entry">
<div className="e-content">{note.content}</div>
<div className="hidden">
<div className="p-name">{note.content}</div>
<a className="u-bridgy-fed" href="https://fed.brid.gy"></a>
<p className="dt-published">{note.date}</p>
</div>
</article>
)
}
Webmentionを送ってBridgy Fedに通知
curl https://fed.brid.gy/webmention -d source=https://dl10yr.com/note/... -d target=https://fed.brid.gy
を送って通知します。
GitHub Actionsでmainブランチにpush時に実行されるようにしました。
変更が入ったファイルが今回の投稿用のmarkdownファイル(/_notes
ディレクトリ以下のファイル)が含まれていれば、そのファイル名からURLを組み立てて、curlを実行するようにしました。
.github/workflows/send-webmention.yaml
name: send webmention
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: false
fetch-depth: 0
- name: Send webmention
uses: actions/setup-node@v3
- run: git fetch origin ${{ github.event.before }} # 直前のコミットハッシュをフェッチします。
- run: git fetch origin ${{ github.sha }} # 最新のコミットハッシュをフェッチします。
- run: node tools/sendWebmention.mjs ${{ github.event.before }} ${{ github.sha }}
sleepさせているのは、Vercelのデプロイが終わるのを待つためです。
投稿ファイルに変更がなければ、curlを実行することはないので、curlを実行するときだけsleepしてます。
tools/sendWebmention.mjs
const child_process = await import('child_process')
const MAX_MENTION_SENDS = 10
const sleep = (sec) => new Promise((res) => setTimeout(res, sec * 1000))
async function sendWebmention(oldCommitHash, newCommitHash) {
const diff = child_process
.spawnSync('git', ['diff', '--name-only', oldCommitHash, newCommitHash])
.stdout.toString()
const files = diff.split('\n')
const filtered = files.filter((file) => file.indexOf('_notes/') !== -1)
if (filtered.length >= 1) {
await sleep(110)
}
for (let i = 0; i < filtered.length && i < MAX_MENTION_SENDS; ++i) {
const filePath = filtered[i].split('/')
const linkPath = filePath.slice(1, -1)
const url = 'https://dl10yr.com/note/' + linkPath.join('/')
// eslint-disable-next-line no-console
console.log('sending webmention of ' + url)
child_process.spawnSync('curl', [
'https://fed.brid.gy/webmention',
'-d',
`source=${encodeURIComponent(url)}`,
'-d',
`target=https://fed.brid.gy`,
])
}
}
const args = process.argv.slice(2)
sendWebmention(args[0], args[1])
今後のToDo
- Postの消去
ここ見る限り、404返すようにして、同じようにwebmention送れば良さそうだけど、送っても上手くいかない... 410のほうが良いのかな? 消去できないと積極的には使えないかなー
https://fed.brid.gy/docs#delete
curl https://fed.brid.gy/webmention -d source=https://dl10yr.com/note/... -d target=https://fed.brid.gy
- フォローとか
これもやりたい - 画像投稿
これはmicroformatsのクラス足すだけでできるはず - リプライ、Favの表示
webmention.jsを使うらしい?
Discussion