📓

Misskeyのノートのサーバー情報の仕様

2023/12/07に公開

TL;DR

/favicon.ico置いてNodeInfoのmetadataにnodeName, nodeDescription, themeColorを追加すればよい。

https://gitlab.com/tkithrta/psh/-/blob/master/static/nodeinfo/2.1.json
https://gitlab.com/acefed/matchbox/-/blob/main/public/nodeinfo/2.1.json

faviconUrl=iconUrlにしたくない場合はmanifest.jsonを置いたりルートパスに存在しているHTMLにアイコンに関するタグを追加する。

はじめに

皆さんノートのサーバー情報はご存知でしょうか。

note

この「Windows95」当時のウィンドウ上部「タイトルバー」のような見た目をしているものがそうです。

https://wiki.misskey.io/ja/function/ticker

このノートのサーバー情報は「InstanceTicker的なもの」として、2020/10/27頃に公開された12.51.0で実装されたものです。

https://github.com/misskey-dev/misskey/releases/tag/12.51.0
https://github.com/misskey-dev/misskey/commit/615fedd64d269c896410713409847ecc4b1c9671

InstanceTicker本家はこちらです。

https://inst.ance.tk/

Misskeyが2023年爆発的に流行った影響もあり、InstanceTicker本家の存在が認知されなくなってしまったので、皆さん今日はInstanceTickerには本家があることを覚えて帰ってくださいね。

本家の作者はアドベントカレンダーでよく隣り合わせになるID:weepさんです(最近アドベントカレンダーで隣り合わせにならない)

https://ticker.hostdon.ne.jp/@instance

まあそれはそれとして、自分でActivityPubを実装すると、このMisskey独自のノートのサーバー情報がActivityPubに関する情報を全く使っておらず、どのように処理されれいるのかよく分からないので、結果こんな感じの残念な仕上がりになってしまいます。

none

何とかしたいですよね。
そこで今回はMisskey v2023.11.1のソースコードをもとに、仕様を解説していきたいと思います。

https://github.com/misskey-dev/misskey

FetchInstanceMetadataService.ts

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts

まず、ノートのサーバー情報に関する処理はすべてpackages/backend/src/core/FetchInstanceMetadataService.ts内にあります。
fetchInstanceMetadata()メソッドで対象のインスタンス(以降サーバーと呼びます)から各情報をスクレイピングするような処理を行っているので、まずはそれぞれ取得しているメソッドを紹介して、その後にfetchInstanceMetadata()の紹介をしたいと思います。

fetchNodeinfo

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L126-L167

fetchNodeinfo()ではNodeInfoのJSONを取得しています。
https://misskey.example.com/.well-known/nodeinfoというWell-known URIへアクセスし、対応しているNodeInfoのバージョンとパスを確認します。

冗長では? と思える仕組みですが、こうすることでキャッシュをうまく機能させたり、NodeInfoのスキーマやパスを知らなくてもアクセス前に確認できるようになっています。
Misskeyではhttps://misskey.example.com/nodeinfo/2.0https://misskey.example.com/nodeinfo/2.1にNodeInfo本体が存在していますが、他のFediverseソフトウェアは違います。

例えばMastodonではhttps://mastodon.example.com/nodeinfo/2.0しかありませんし、Pleromaだとhttps://pleroma.example.com/nodeinfo/2.0.jsonhttps://pleroma.example.com/nodeinfo/2.1.jsonのように.jsonがつきます。
ちなみに私が自作したActivityPub実装では負荷軽減のため静的ファイルとして扱えるようにしているので、Pleromaと同じく.jsonがついているものを処理できるようにしています。

https://nodeinfo.diaspora.software/

話がそれましたが、/.well-known/nodeinfoパス内にあるlink.hrefのURLから情報を取得する処理を行っています。

fetchDom

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L170-L181

fetchDom()ではルートパスに存在しているHTMLを取得しています。
無駄では? と思える仕組みですが、ノートのサーバー情報ではNodeInfoのmetadataにあるものを使用しているにもかかわらず、NodeInfoを実装していてもmetadataに情報がないことがあります。
特にMastodonは多くの情報をMastodon独自のAPIから取得できるようにしているため、metadataには情報が一切ありません。ほんまこいつ……。
つまりノートのサーバー情報でMastodonの情報を表示するためにこのメソッドがとても重要な役割を果たすんですね。

fetchManifest

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L184-L192

fetchManifest()ではPWAなどで用いられるmanifest.jsonを取得しています。
不要では? と思える仕組みですが、実際ノートのサーバー情報ではあまり使われません。
主に後述するfetchIconUrl()で高画質のアイコンを取得するために使用するようです。
また、HTMLにテーマカラーなど必要な情報が記載されていなかったり、宗教上の理由でHTMLを使っていなかったり、そもそもルートパスで404が帰ってきたりする実装もたまにあったりするので、そういった場合はmanifest.jsonから取得できたりします。

fetchFaviconUrl

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L195-L218

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

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L221-L247

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()でアイコンに関するタグがあるか確認します。
このアイコンに関するタグとは何ぞやといった話はものすごく長いレビューが行われた末実装されたものなので、詳しくはここで解説しません。
以下プルリクエストを参照してください。

https://github.com/misskey-dev/misskey/pull/6591
https://github.com/misskey-dev/misskey/pull/8220

getThemeColor

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L250-L259

getThemeColor()ではノートのサーバー情報で使用するカラーコードをを取得します。
まず最初にNodeInfoのmetadataにあるthemeColor、もしなければHTMLにあるmetaタグのtheme-color、それでもなければmanifest.jsonのtheme_colorを確認します。
意外とシンプルですが、3つとも存在しなければ後述する#777777が使われます。
ノートのサーバー情報がグレーのサーバーは、自作したActivityPub実装であることが多いのですが、これらが存在していなかったのが原因だったんですね。

ノートのサーバー情報を彩るためには、NodeInfoのmetadataのthemeColorにカラーコードを追加しましょう。

getSiteName

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L262-L284

getSiteName()ではノートのサーバー情報で使用するサーバー名を取得します。
まず最初にNodeInfoのmetadataにあるnodeNameとname、もしなければHTMLにあるmetaタグのog:title、それでもなければmanifest.jsonのnameとshort_nameを確認します。
なぜかHTMLタグにあるTitleは見ないんですねこれ。

NodeInfoには別途softwareのnameが存在しますが、これはソフトウェア名なのでサーバー名として使われません。
ノートのサーバー情報に自作したActivityPub実装の名前を表示するためには、NodeInfoのmetadataのnodeNameにサーバー名を追加しましょう。

getDescription

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L287-L313

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

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L65-L123

これらすべてを使用しているメソッドが最初に紹介した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は以下のとおりです。

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/backend/src/core/FetchInstanceMetadataService.ts#L20-L37

MkInstanceTicker.vue

https://github.com/misskey-dev/misskey/blob/2023.11.1/packages/frontend/src/components/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