MisskeyのAPIをkotlinで呼び出してみる

twitterのAPI制限が厳しくなったため他のサービスを探したところ、MisskeyでもAPIを公開しているのでkotlinで呼び出しできるか試してみました。

以前にもMastodonというサービス(ソフトの名称でもあります)がありましたが、
MisskeyもMastodonと同様に分散型のSNSで複数のサーバに分かれてそれぞれ運営されています。

準備

ここでは、Misskeyサーバの中でも最大手である Misskey.io でAPIを試してみます。

Misskey APIの主な仕様は以下のようになります。

  • APIはPOSTメソッドで呼び出します。(一部例外を除く)
  • データは主にJSON形式でやりとりします。
  • API呼び出し時にはリクエストボディにアクセストークンを指定します。

APIとアクセストークンについては以下にドキュメントがあります。
https://misskey-hub.net/docs/api

APIの呼び出しには認証のためアクセストークンが必要です。

misskey.ioでアカウントを作成し、設定のAPIから『アクセストークンの発行』を行います。
取得したアクセストークンは、”i”というパラメータ名でリクエストボディに含める必要があります。

開発

IntelliJでKotlin/Gradleのプロジェクトを作成します。

APIではJsonを使用するため、Jsonを扱えるjacksonというライブラリを追加します。
build.gradle.kts の dependencies の箇所に jackson-module-kotlin を追加します。

dependencies {
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.2")
}

サンプルコードを記載するのに Main.kt ファイルを作成しておきます。

object Main {
  @JvmStatic
  fun main(args: Array) {
  }
}

ローカルタイムライン取得

APIリファレンスを参照し、API呼び出しのコードを実装します。
まずはローカルタイムラインを取得します。
ローカルタイムラインは各ユーザーの投稿したノート(twitterでのツイートにあたります)を取得できます。

ローカルタイムラインAPIのリファレンスは以下にあります。
https://misskey-hub.net/docs/api/endpoints/notes/local-timeline.html

いくつかパラメータがありますが、あまり必須のものはなさそうです。
limitが取得する最大件数のようです。
また、ここでは省略されていますが、アクセストークンを”i”というパラメータ名で指定する必要があります。
とりあえず動作確認のため、パラメータiとlimitだけ指定します。

レスポンスではNoteの配列が返ります。
Noteにはいくつかパラメータがありますが、必要そうなのはid, createdAt, text, userくらいでしょうか。

パラメータ名のuserではUserが返ります。
こちらも必要そうなのはid, username, nameくらいでしょうか。

以上の仕様から、APIでやり取りするデータの入れ物となるデータクラスを作成します。

  data class LocalTimelineReq(
    val i: String,
    val limit: Int = 10
  )

  @JsonIgnoreProperties(ignoreUnknown = true)
  data class User(
    val id: String,
    val username: String,
    val name: String?
  )

  @JsonIgnoreProperties(ignoreUnknown = true)
  data class Note(
    val id: String,
    val createdAt: String,
    val text: String?,
    val user: User
  )

注意点として、jacksonの仕様でオブジェクトにない項目があるとエラーになるので、不要な項目は無視するよう、
@JsonIgnoreProperties(ignoreUnknown = true) を指定します。
また、ドキュメントには記載がないですが、User.nameはnullの場合があるのでString?型にしておきます。

では実際の呼び出しのコードです。
呼び出しのパラメータを作成し、jacksonObjectMapperでJSONに変換します。

    val input = LocalTimelineReq(
      i = accessToken,
      limit = 20
    )

    val mapper = jacksonObjectMapper()
    val inputJson = mapper.writeValueAsString(input)

URL, Content-Type, 呼び出しのパラメータを指定してリクエストを作成します。

    val url = "https://misskey.io/api/notes/local-timeline"

    val req =
      HttpRequest
        .newBuilder()
        .uri(URI.create(url))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(inputJson))
        .build()

リクエストを使用してAPIを呼び出し、レスポンスを取得します。

    val client = HttpClient.newBuilder().build()
    val res = client.send(req, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))

レスポンスからデータのJSONをデータクラスのオブジェクトに変換します。
ここではNoteの配列が取得できます。

    val resultJson = res.body()
    val output = mapper.readValue(resultJson, Array::class.java)

取得したデータを適当に出力します。

    for (p in output) {
      if (p.text != null) {
        val user = p.user.name ?: p.user.username
        println("user=${user} text=${p.text}")
      }
    }
  }

コードを実行してノートが取得できれば成功です。
アクセストークンが無効な場合等は403エラーが返ります。

ノートの投稿

次はノートを投稿してみます。

APIリファレンスは以下にあります。
https://misskey-hub.net/docs/api/endpoints/notes/create.html

必要そうなパラメータは visibility, textでしょうか。

レスポンスではcreatedNoteというパラメータ名が返ります。

以上の仕様から、データクラスを作成します。

  data class CreateNoteReq(
    val i: String,
    val visibility: String,
    val text: String?
  )

  @JsonIgnoreProperties(ignoreUnknown = true)
  data class CreateNoteRes(
    val createdNote: Note
  )

実際の呼び出しのコードです。
ノート作成用のデータクラスを作成します。

    val input = CreateNoteReq(
      i = accessToken,
      text = message,
      visibility = visibility
    )

    val inputJson = mapper.writeValueAsString(input)

URLは /api/notes/create を指定します。

    val url = "https://misskey.io/api/notes/create"
    val req =
      HttpRequest
        .newBuilder()
        .uri(URI.create(url))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(inputJson))
        .build()

返されたレスポンスからCreateNoteResを取得します。

    val client = HttpClient.newBuilder().build()
    val res = client.send(req, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))
    val output = mapper.readValue(resultJson, CreateNoteRes::class.java)
    println("create: id=${output.createdNote.id} id=${output.createdNote.createdAt} ")

ノートの新規に発行されたIDが取得できれば成功です。

このように、kotlinのデータクラスとjacksonライブラリを使うとJSON形式を用いたAPI呼び出しをスマートに開発することができます。

サンプルコード

https://github.com/ito-mmj/misskey-sample

関連記事

最近の記事 おすすめ記事
  1. 新人さん向けの品質についての読書会

  1. 京都オフィス忘年会2022

  2. Rails7にHotwireを使ってみた

  3. KotlinとNull Safety

カテゴリー

アーカイブ

検索


TOP
TOP