OpenStickerについて

OpenStickerというものを公開しています。
Mastodon向けのカスタムCSSで、#InstanceTickerのようなものです。

OpenSticker

InstanceTickerとの違い

OpenStickerは#InstanceTicker(MITライセンス)をベースにしているのでデザイン面での差異はほとんどありません。

違いを以下に挙げておきます。

  • ほぼ全部オープンソースです
    インスタンス情報等もすべてGitHubリポジトリへのPRベースで編集・追加することができます。
  • 自動化されています
    現段階ではPRしたときの鯖缶認証(後述)と、PRのマージ後にデータ(JSON/CSS)の作成(更新)が自動化されています。
  • faviconベースです
    PRによりfavicon以外の画像を指定することができますが、デフォルトは各サイトのfaviconです。標準設定から変えていない場合はそれを判定して同じファイルを提示することでリクエスト数を減らします
  • 対応プラットフォームを絞りました
    現段階ではMastodon向けCSSと、Mastodon, Pleroma, Misskey(v12), Misskey(v11/v10), PixelFedの情報表示に対応しています。
  • 連合先のインスタンスだけにデータを絞れる
    #InstanceTickerでは1,000を超えるサーバのデータを全て用意しているため、連合していないサーバ用のCSSも含まれデータ通信量の増大につながっていましたが、OpenStickerは連合先をAPIで取得し、連合先だけの無駄のないCSSを生成できます。

使い方

基本情報

JSON

CSS(Mastodon向け)

連合のみのCSS(Mastodon向け)

鯖缶向け

カスタムCSSとして

改造要らずでとりあえず導入できます。

OpenStickerで「読み込む」を押して、出てきたのを管理 > サイト設定 > カスタムCSSに貼り付けて完了です。

更新時も同じように行います。

連合先だけのデータに絞りたいときは、「Mastodon向けCSS」のセレクタをクリックし「Mastodon向け連合先だけCSS」を押し、自分のインスタンスのドメインを入力して読み込んでください。

メリット

  • 一番楽。改造が要らない。改造してしまうと本体アップデートへの追従に苦労することがある。

デメリット

  • 全ユーザに適用されてしまう。使いたくない人も使わざるを得ない。
  • 更新時は同じように手動でで再登録しなければならない。

テーマとして

実装例
app/javascript/styles/opensticker.scssを作成してOpenStickerのCSSを@importする。
config/themes.ymlでテーマを追加する。
config/initializers/content_security_policy.rbでCORS対策をする(重要)
config/locales/en.ymlconfig/locales/ja.ymlでテーマの名前を決める。

実装例をそのまま取り込むと、今tootsuite/mastodonにcutlsが出しているPRもついでに取り込んでしまうことになるので注意してください。実装例ではcutls.comの連合先だけのCSSを取得しています。

メリット

  • 改造が要るが比較的楽。テーマとポリシーしかいじってない。改造箇所が少なく比較的stableなのでコンフリクトしにくい。
  • 使いたい人だけテーマを変えればいい。

デメリット

  • とはいっても改造が要る。AGPLに従った運用をしてね。
  • 上のやり方だとダークテーマにしか適用できない。ライトテーマやハイコントラストテーマに適用するためにはその数だけテーマを新しく作る必要がある。
  • 使う人にとってはデータ通信量の削減にはならない。

コンポーネントとして

cutls/os-mastodon-componentyarn addすることで、ReactのComponentとして使え、あとは設定画面にチェックボックスを作り、initial stateを変えることでWebUIに伝えて表示/非表示を変える。

実装例。10ファイル以上変更点があるのでここには記しません。

メリット

  • チェックボックスを入れたらテーマに関係なくOpenStickerを表示できる。
  • CSSではなくJSONをfetchするので通信容量が1/5程度になる。

デメリット

  • 改造が要る。AGPLに従った運用をしてね。
  • 改造箇所が多い上に将来的にコンフリクト起こしそう

将来的にはVue用のコンポーネントも用意してMisskey対応もしたい。

非鯖缶向け

Chrome拡張であるStylusなどを使ってください。

クライアント開発者向け

JSONを取得できます。

JSONの中身

1
2
3
data: IData
updated: Fri Aug 07 2020 04:15:24 GMT+0000 (UTC) //例
default: IDefault

IData

1
2
3
4
5
6
7
8
9
10
interface IData {
type: 'mastodon'|'pleroma'|'misskey'|'misskeylegacy'|'pixelfed' //misskeyはv12でなければlegacy
name: string
bgColor?: string[] | null //nullならIDefault[type].bgColorを参照
fontColor?: string | null //nullならIDefault[type].fontColorを参照
favicon: string //普通はこっちを読んでください PNG/15px, 15px
withoutCDN: string //faviconの生データまたはs.0px.io/a/md|pl|mi|ml|pf(各種デフォルトロゴ画像)
domain: string
isDefault: boolean //faviconが変更されているかどうか。これがfalseでもbgColorやfontColorは変更されている可能性あり。
}

IDefault

1
2
3
4
5
6
7
interface IDefault {
mastodon: {bgColor: string[], fontColor: string}
pleroma: {bgColor: string[], fontColor: string}
misskey: {bgColor: string[], fontColor: string}
misskeylegacy: {bgColor: string[], fontColor: string}
pixelfed: {bgColor: string[], fontColor: string}
}
  • fontColorについて
    /#[0-9A-F]{3,6}/で示される文字列(#000や#ffffffなど)
  • bgColorについて
    fontColor同様の色の表現の配列。

CSSにおける表現

[‘#26a’]と書かれていた場合
[===========]
 #26a   透明
となるようにグラデーションをします。

[‘#000’, ‘#e0e0e0’]と書かれていた場合
[============================]
 #000       #e0e0e0       透明
50%の位置で2番目の色になるようにグラデーションします。
このとき#e0e0e0には透過を行いません。

以下同様にn個の配列に対して0, 1/n, … n-1/n, 透明
となるようにします。

技術要綱

コンテンツ配信

全てCloudflareが通ってます。あまり使いたくはなかったけどしょうがない…

画像最適化

images.weserv.nlを使っています。icoがfaviconで流れてきてもこのサービスでpngにして処理にかけてます。また、縦横15pxに変換するのもこのサービスがやってます。なお、このソフト自体はオープンソースです。

画像配信にはCloudflareが入っているそうなので、Cloudflareの2重使用になります。

ウェブサーバ

Nginx。みんな大好き。

クラウドサービス

OracleCloud。タダ運用。1Core/1GBで十分。

バックエンド

cutls/OpenSticker
Denoで書いてみたけど、まだパッケージが無さ過ぎるのでかなり辛かった。(Nodeのをそのまま持ってこれるかはソースコード/dependency次第)

まぁTypeScriptがそのまま書けるのはよい。JSON5を処理するために、JSON5をフォークして、index.jsだけindex.tsにし適当に型定義したうえでDeno用ライブラリとして使ってます。oakというkoaのDeno版を試しに使ってみました。

フロントエンド

cutls/os-fe
Vueでサクッと書いたのでTypeScriptすら使ってないです。

favicon取得API

cutls/fedi-favicon-api
どうしてもJimpが使いたかったけど、Deno化は無理そうなので別出しした。リポジトリに叩き方載ってます。

Jimpは画像の類似度判定がめっちゃくちゃ簡単に書けるのがいいです。本場のkoaやスクレイピング(metaタグでfavicon判定)用にcheerio、Denoみたいにfetchをそのまま持ち込めないのでaxiosを導入してます。

PR鯖缶認証bot

プロプライエタリです。
Webhookを受けてGitHub ApplicationとしてそのPRに認証用リンクをコメントします。

そのリンクを踏むと、モデレータAPIへのアクセス権を要求するOAuth認証が出るので、許可すると”Verified by bot”と改めてコメントされます。

あとは手動です。また、Mastodon限定で、Pleroma, Misskey等は手動で認証します。