マストドンのストリーミングAPIで取得できるデータ形式の違い


拙作「G+Don」の開発にあたり、ストリーミングAPIも当然使っているわけですが、公式ドキュメントにどうやらなさそうだけど非常に大事そうな情報があったので、覚書きとして掲載します。

事の発端

 G+Donではダイレクトメッセージをやりとりするのに、マストドンの標準的なタイムラインの表示やG+Donのタイムラインは使わず、ハングアウトやLINE等のメッセンジャーよろしくなレイアウトを採用していたりします。

 スクロールすることで/api/v1/timelines/directを呼び出して更新するようにして、最低限表示できるようにはしていたのですが、/api/v1/streaming/?stream=directを実行してトゥートが流れてくるのを待っていたのですが、プログラム上、全然流れ込んでこない・・・。

 これはおかしいと思い、調べてみようと本腰を入れました。

ストリーミングAPI

マストドンのストリーミングAPIの公式ドキュメントは次のものです。

Streaming API - tootesuite/documentation

Streaming API - Mastodon documentation

個人的には次のサイトに超絶助けられてます。
Mastodon APIを使ってみる

これらで示されているように、ストリーミングAPIには次の種類が存在します。

  • user
  • list
  • public
  • public/local
  • hashtag
  • hastag/local
  • direct

 普通のAPIのほうでも同名でtimelinesに存在するため説明不要だと思います。ストリーミングAPIではデータの流れ方が普通のAPIと違い、何か更新があったらこちらがパックリ開けた口(ストリーミングAPIの実行)にその都度更新データが流れ込んできます。
 仕組みはWebSocketを使っているので、こうしたことが容易に実現できるのだそうです。

 公式での説明ではデータには次の種類(Event types)があります。

  • update
  • delete
  • notification
  • filters_changed

それぞれ流れ込んでくるデータの形式は異なります。

test.js
//---updateの場合
var a = {
  "event" : "update",
  "payload" : "{id..."
};
//payloadはStatusオブジェクト

//---deleteの場合
var a = {
  "event" : "notification",
  "payload" : "12345..." 
};
//payloadは削除されたトゥートのID

//---notificationの場合
var a = {
  "event" : "notification",
  "payload" : "{id..." 
};
//payloadはNotificationオブジェクト

とりあえずトゥートを確認したいなら、updateさえ正しく取得してアプリ側で解釈できればいいわけですが、実はこの4つ以外にもデータの種類が存在します。

ダイレクトメッセージのデータ形式

 ダイレクトメッセージはその性質上、@メンションがついているためにevent=notificationでもストリーミングに流れ込んできます。(user)
 ダイレクトメッセージを取得する/api/v1/streaming/stream=directでは、実はデータが次のように流れ込んできます。

test.js
var a = {
  "event" : "conversation",
  "payload" : {
    "id" : "123456",
    "unread"  : true,
    "accounts" : [
      {
        "id" : "934949",
        "username" : "hogehoge",
        ...
        //---中身はAccountオブジェクト
      }
    ],
    "last_status" : {
      //---中身はStatusオブジェクト
    }
  }
};

そう。eventが conversation なのです。

userやpublicなどと同じくupdateで流れてくるんだろうなと思っていると、痛い目を見ます。公式ドキュメントに記載がないため、最初は気づかないと思います。
事実私もきづかずにupdateで捕捉できると勘違いしていたため、アプリ側で解決が遅れました。

 それから、/api/v1/streaming/?stream=directだと、event=deleteのデータが流れてこないようです。ダイレクトメッセージの削除を捕捉するには、userのストリーミングAPIも合わせて使う必要がありそうです。
(このあたりは引き続き動作検証中です)

ストリーミングAPIのデータの確認方法

 こんなときにでもChromeのDevToolsは活用できます。ストリーミングAPIもNetworkタブで確認できます。

 赤枠で囲んだところがストリーミングAPIを呼び出した箇所・タイミングです。以後、データを受信すると、右パネルのMessagesタブ内で確認できるようになります。

 ストリーミングAPIを実装するときはとりあえず実行できるところまで実装し準備しておきましょう。アプリ側でどう表示するとかはひとまず置いておき、先にこうして確認できれば、後はスムーズに開発を継続できると思います。

 なんといいますか、WebSocketって便利ですね。