Misskeyのノートのサーバー情報の仕様
TL;DR
/favicon.ico置いてNodeInfoのmetadataにnodeName, nodeDescription, themeColorを追加すればよい。
faviconUrl=iconUrlにしたくない場合はmanifest.jsonを置いたりルートパスに存在しているHTMLにアイコンに関するタグを追加する。
はじめに
皆さんノートのサーバー情報はご存知でしょうか。
この「Windows95」当時のウィンドウ上部「タイトルバー」のような見た目をしているものがそうです。
このノートのサーバー情報は「InstanceTicker的なもの」として、2020/10/27頃に公開された12.51.0で実装されたものです。
InstanceTicker本家はこちらです。
Misskeyが2023年爆発的に流行った影響もあり、InstanceTicker本家の存在が認知されなくなってしまったので、皆さん今日はInstanceTickerには本家があることを覚えて帰ってくださいね。
本家の作者はアドベントカレンダーでよく隣り合わせになるID:weepさんです(最近アドベントカレンダーで隣り合わせにならない)
まあそれはそれとして、自分でActivityPubを実装すると、このMisskey独自のノートのサーバー情報がActivityPubに関する情報を全く使っておらず、どのように処理されれいるのかよく分からないので、結果こんな感じの残念な仕上がりになってしまいます。
何とかしたいですよね。
そこで今回はMisskey v2023.11.1のソースコードをもとに、仕様を解説していきたいと思います。
FetchInstanceMetadataService.ts
まず、ノートのサーバー情報に関する処理はすべてpackages/backend/src/core/FetchInstanceMetadataService.ts
内にあります。
fetchInstanceMetadata()
メソッドで対象のインスタンス(以降サーバーと呼びます)から各情報をスクレイピングするような処理を行っているので、まずはそれぞれ取得しているメソッドを紹介して、その後にfetchInstanceMetadata()
の紹介をしたいと思います。
fetchNodeinfo
fetchNodeinfo()
ではNodeInfoのJSONを取得しています。
https://misskey.example.com/.well-known/nodeinfo
というWell-known URIへアクセスし、対応しているNodeInfoのバージョンとパスを確認します。
冗長では? と思える仕組みですが、こうすることでキャッシュをうまく機能させたり、NodeInfoのスキーマやパスを知らなくてもアクセス前に確認できるようになっています。
Misskeyではhttps://misskey.example.com/nodeinfo/2.0
とhttps://misskey.example.com/nodeinfo/2.1
にNodeInfo本体が存在していますが、他のFediverseソフトウェアは違います。
例えばMastodonではhttps://mastodon.example.com/nodeinfo/2.0
しかありませんし、Pleromaだとhttps://pleroma.example.com/nodeinfo/2.0.json
やhttps://pleroma.example.com/nodeinfo/2.1.json
のように.jsonがつきます。
ちなみに私が自作したActivityPub実装では負荷軽減のため静的ファイルとして扱えるようにしているので、Pleromaと同じく.jsonがついているものを処理できるようにしています。
話がそれましたが、/.well-known/nodeinfo
パス内にあるlink.hrefのURLから情報を取得する処理を行っています。
fetchDom
fetchDom()
ではルートパスに存在しているHTMLを取得しています。
無駄では? と思える仕組みですが、ノートのサーバー情報ではNodeInfoのmetadataにあるものを使用しているにもかかわらず、NodeInfoを実装していてもmetadataに情報がないことがあります。
特にMastodonは多くの情報をMastodon独自のAPIから取得できるようにしているため、metadataには情報が一切ありません。ほんまこいつ……。
つまりノートのサーバー情報でMastodonの情報を表示するためにこのメソッドがとても重要な役割を果たすんですね。
fetchManifest
fetchManifest()
ではPWAなどで用いられるmanifest.jsonを取得しています。
不要では? と思える仕組みですが、実際ノートのサーバー情報ではあまり使われません。
主に後述するfetchIconUrl()
で高画質のアイコンを取得するために使用するようです。
また、HTMLにテーマカラーなど必要な情報が記載されていなかったり、宗教上の理由でHTMLを使っていなかったり、そもそもルートパスで404が帰ってきたりする実装もたまにあったりするので、そういった場合はmanifest.jsonから取得できたりします。
fetchFaviconUrl
fetchFaviconUrl()
ではノートのサーバー情報で使用するFaviconのURLを取得します。
まずはfetchDom()
で以下のようなタグがあるか確認します。
<link rel="icon" href="/path/to/favicon.ico" type="image/x-icon" />
あればhttps://misskey.example.com/path/to/favicon.ico
から取得します。
もしなければhttps://misskey.example.com/favicon.ico
から取得します。
ブラウザでFaviconを表示するのと似た処理ですね。
fetchIconUrl
fetchIconUrl()
ではFaviconより高画質なIconのURLを取得します。
まずはfetchManifest()
で以下のようなオブジェクトがあるか確認します。
{ "icons": [{ "src": "/path/to/192.png" }, { "src": "/path/to/512.png" }]}
あればhttps://misskey.example.com/path/to/192.png
から取得します。
配列の最初から取得するため、この場合より高画質なhttps://misskey.example.com/path/to/512.png
は取得されません。
あくまでFaviconより高画質かどうかが重要なんですね。
もしなければfetchDom()
でアイコンに関するタグがあるか確認します。
このアイコンに関するタグとは何ぞやといった話はものすごく長いレビューが行われた末実装されたものなので、詳しくはここで解説しません。
以下プルリクエストを参照してください。
getThemeColor
getThemeColor()
ではノートのサーバー情報で使用するカラーコードをを取得します。
まず最初にNodeInfoのmetadataにあるthemeColor、もしなければHTMLにあるmetaタグのtheme-color、それでもなければmanifest.jsonのtheme_colorを確認します。
意外とシンプルですが、3つとも存在しなければ後述する#777777
が使われます。
ノートのサーバー情報がグレーのサーバーは、自作したActivityPub実装であることが多いのですが、これらが存在していなかったのが原因だったんですね。
ノートのサーバー情報を彩るためには、NodeInfoのmetadataのthemeColorにカラーコードを追加しましょう。
getSiteName
getSiteName()
ではノートのサーバー情報で使用するサーバー名を取得します。
まず最初にNodeInfoのmetadataにあるnodeNameとname、もしなければHTMLにあるmetaタグのog:title、それでもなければmanifest.jsonのnameとshort_nameを確認します。
なぜかHTMLタグにあるTitleは見ないんですねこれ。
NodeInfoには別途softwareのnameが存在しますが、これはソフトウェア名なのでサーバー名として使われません。
ノートのサーバー情報に自作したActivityPub実装の名前を表示するためには、NodeInfoのmetadataのnodeNameにサーバー名を追加しましょう。
getDescription
getDescription()
ではサーバーの説明を取得します。
なのでノートのサーバー情報では使用しません。
例えばhttps://misskey.example.com/instance-info/misskey.io
から確認できる連合のサーバー情報で使用します。
まず最初にNodeInfoのmetadataにあるnodeDescriptionとdescription、もしなければHTMLにあるmetaタグのdescriptionとog:description、それでもなければmanifest.jsonのnameとshort_nameを確認します。
サーバーの説明を表示すると謎のHTMLタグが表示されることが多々ありますが、あれがこれです。
fetchInstanceMetadata
これらすべてを使用しているメソッドが最初に紹介したfetchInstanceMetadata()
です。
info, dom, manifestにfetchNodeinfo()
, fetchDom()
, fetchManifest()
からそれぞれJSONやHTMLを格納し、favicon, iconはアイコン取得可能なURLを代入、themeColor, name, descriptionにはinfo, dom, manifestから文字列を代入します。
ついでにNodeInfoから取得できるsoftwareName, softwareVersion, openRegistrations, maintainerName, maintainerEmailも代入します。
これらの情報は連合のサーバー情報で使用するほか、Misskeyのサーバー管理を行う上でも便利な情報です。
ただmaintainer nameとmaintainer emailはMisskeyぐらいでしか使われていないmetadataなので、MastodonやPleromaの連合のサーバー情報は「管理者 (不明) ((不明))」になりがちです。
サーバー情報で使用するNodeInfoは以下のとおりです。
MkInstanceTicker.vue
最後にpackages/frontend/src/components/MkInstanceTicker.vue
の紹介です。
「InstanceTicker的なもの」本体ですね。
使用する情報はfaviconUrl, name, themeColorです。
先に述べた通り、ここで言うnameとはソフトウェア名ではなくサーバー名なので注意が必要です。
themeColorは存在しない場合#777777
が使用されます。
また、faviconUrlが存在しない場合、おそらくiconUrlを使用するようになっていると思われます。
おわりに
/favicon.ico置いてNodeInfoのmetadataにnodeName, nodeDescription, themeColorを追加すればよいことが分かりました。
faviconUrl=iconUrlにしたくない場合はmanifest.jsonを置いたりルートパスに存在しているHTMLにアイコンに関するタグを追加しましょう。
Wikiに記載の通り、InstanceTicker本家は人力で行っている箇所が多いのですが、Misskeyの「InstanceTicker的なもの」はとにかく徹底的にプログラムされており、自動的に情報を取得、表示されるようになっています。
ActivityPubのように仕様を理解すれば誰でも簡単に実装できるものですので、皆さんもMisskeyやMastodonをカスタマイズしたり、ActivityPubやNodeInfoを実装する際参考にしてみてはいかがでしょうか。
Discussion