JetBrains Space ヘルプ

(Kotlin) チャットボットの作成方法

チャットボットとは何ですか ? これは、独自のチャットチャネルで Space ユーザーと通信する Space アプリケーションです。最低限実行可能なボットは次のことを行う必要があります。

  • ユーザーがチャネルに / (スラッシュ) を入力すると、使用可能なコマンドのリストが表示されます。

  • 少なくとも 1 つのコマンドを指定します。ユーザーがこのコマンドをチャネルに送信した後、ボットは何かを実行してからメッセージで応答する必要があります。

何をしたらいいでしょう

もちろん、初めてのチャットボットでも ! 早速、「リマインダー」ボットを歓迎します。

ボットは、一定時間が経過するとユーザーにリマインダーを送信します。例: ユーザーが remind 60 take a nap コマンドをボットに送信すると、60 秒後にボットは take a nap メッセージで応答します。また、ボットには、要求されたときに help を提供するコマンドがあります。

このチュートリアルでは、チャットボット作成プロセス全体をガイドしますが、結果のソースコード(英語)はいつでもダウンロードできます。

チャットボット作成スターターキット

旅の途中で何が必要になるでしょうか?

Intellij IDEA

JetBrains IntelliJ IDEA

ボットを Kotlin で作成します。任意の IDE を使用できますが、このチュートリアルでは IntelliJ IDEA を使用することを暗示しています。

Ktor framework

Ktor フレームワーク (英語)

これは、サーバー、クライアント、モバイル、ブラウザーベースのアプリなど、あらゆる種類の接続アプリケーションを簡単に作成できるフレームワークです。これは Gradle 依存関係の 1 つとして取得されるため、ユーザー側で追加のアクションは必要ありません。もちろん、このチュートリアル以外でも、Node.js、ASP.NET などの任意の Web フレームワークを使用して Space ボットを作成できます。

Space SDK

Space SDK

アプリケーションの開発トピックからわかるように、アプリケーションは Space HTTP API を使用して Space と通信する必要があります。Space アプリ開発者の負担を軽減するために、Kotlin および .NET 用の Space SDK を提供しています。SDK には、複数の高レベルクラスを使用して Space での認証と通信を簡単に行うことができる HTTP API クライアントが含まれています。Ktor フレームワークと同様に、SDK を Gradle 依存関係として取得します。

ngrok

トンネリングサービス

このようなサービスは、ローカルサーバーを公共のインターネットに公開します。これにより、チャットボットをローカルで実行し、パブリック URL (チャットボットのエンドポイントとして指定します) を介して Space からアクセスできるようになります。例: この目的には、ngrok(英語)PageKyte(英語)、または別のトンネリングサービスを使用できます。トンネリングサービスの使用を開始するには、サービスクライアント (ngrok client(英語)PageKyte クライアント (英語)) をダウンロードする必要があります。私たちの目的には、ngrok または PageKyte の無料プランで十分です。

ステップ 1. Ktor プロジェクトを作成する

  1. Intellij IDEA を開きます。

  2. ファイル | 新規 | プロジェクトで新しいプロジェクトの作成を開始します。

  3. テンプレートのリストで、Ktor を選択します。

  4. プロジェクト名前Web サイト名を指定し、ビルドシステムGradle Kotlin を選択し、サンプルコードの追加チェックボックスをオフにします。

    New Ktor project
  5. 次へをクリックします。Ktor プラグインはインストールしないため、次のページで作成をクリックするだけです。

  6. 以上です ! これで、空の Ktor プロジェクトができました。

    New Ktor project

ステップ 2. Space SDK とその他の依存関係を取得する

チャットボットには次のライブラリが必要です。

  • JVM 用 Space SDK

  • FasterXML/jackson: JSON ペイロードを操作します。

  • Ktor HTTP クライアント: 汎用 Ktor アプリは HTTP クライアントのライブラリを参照しません。Space にリクエストを送信するにはクライアントが必要です。ここでは CIO Ktor HTTP クライアント(英語)を使用しますが、HTTP クライアントには他の Web エンジンを使用することもできます。

  1. build.gradle.kts を開いて以下を追加します。

    • repositories セクションへ:

      maven("https://maven.pkg.jetbrains.space/public/p/space/maven")
    • dependencies セクションに、必要なライブラリに依存関係を追加します。

      implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3' implementation "org.jetbrains:space-sdk-jvm:$space_sdk_version" implementation "io.ktor:ktor-client-core:$ktor_version" implementation "io.ktor:ktor-client-cio:$ktor_version"
      implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version") implementation("org.jetbrains:space-sdk-jvm:$space_sdk_version") implementation("io.ktor:ktor-client-core:$ktor_version") implementation("io.ktor:ktor-client-cio:$ktor_version")

    gradle.properties で、必要なパッケージのバージョンを指定します。

    ktor_version=2.0.3 jackson_version=2.13.3 # We use SDK v.106390, but when you read this tutorial, a newer version may be available. # To find out which SDK version is the latest available: open API Playground, # in the "Code" section on the right, choose "Kotlin SDK", and click "Set up dependency..." space_sdk_version=106390-beta
  2. このアプリケーションのテストは作成しないため、dependencies セクションからすべての testImplementation 依存関係をクリーンアップします。

    build.gradle.kts は次のようになります。

    val ktor_version: String by project val kotlin_version: String by project val logback_version: String by project val space_sdk_version: String by project val jackson_version: String by project plugins { application kotlin("jvm") version "1.7.10" } group = "com.example" version = "0.0.1" application { mainClass.set("com.example.ApplicationKt") val isDevelopment: Boolean = project.ext.has("development") applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment") } repositories { mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/space/maven") } dependencies { implementation("io.ktor:ktor-server-core-jvm:$ktor_version") implementation("io.ktor:ktor-server-netty-jvm:$ktor_version") implementation("ch.qos.logback:logback-classic:$logback_version") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version") implementation("org.jetbrains:space-sdk-jvm:$space_sdk_version") implementation("io.ktor:ktor-client-core:$ktor_version") implementation("io.ktor:ktor-client-cio:$ktor_version") }

    gradle.properties は次のようになります。

    ktor_version=2.0.3 kotlin_version=1.7.10 logback_version=1.2.3 jackson_version=2.13.3 kotlin.code.style=official space_sdk_version=106390-beta

  3. Gradle ウィンドウで、すべての Gradle プロジェクトを再ロードしますをクリックして、Gradle に必要な依存関係をダウンロードさせます。

    Update dependencies
  4. 終わり ! これで、プロジェクトに Space SDK が追加されました。

ステップ 3. トンネリングサービスを実行する

Space にチャットボットを登録する前に、そのチャットボットの公開 URL を取得する必要があります。開発環境はおそらく NAT の背後にあるため、URL を取得する最も簡単な方法はトンネリングサービスを使用することです。この例では、ngrok を使用します。

  1. ngrok クライアント(英語)をダウンロードして解凍します。

  2. ターミナル (macOS または Linux) またはコマンドライン (Windows) で、ngrok ディレクトリを開きます。

  3. デフォルトでは、Ktor プロジェクトはポート 8080 で HTTP サーバーを実行するように構成されています (これは resources/application.conf ファイルで確認できます)。このポートに対してトンネリングを実行します。

    ./ngrok http 8080
  4. ngrok サービスが開始されます。次のようになります。

    Session Status online Account user@example.com (Plan: Free) Version 3.0.6 Region United States (us) Latency - Web Interface http://127.0.0.1:4040 Forwarding https://98af-94-158-242-146.ngrok.io -> http://localhost:8080 Connections ttl opn rt1 rt5 p50 p90 0 0 0.00 0.00 0.00 0.00

    ここで注目するのは Forwarding 行です。これにはパブリック URL が含まれています。ngrok は、トンネリングサービスを使用して、この URL からのリクエストをローカルホストにリダイレクトします。上記の例では、アドレスは https://98af-94-158-242-146.ngrok.io ですが、ngrok がこれらのランダムな URL を動的に生成するため、あなたの場合は別のものになります。

  5. よくやった ! これで、トンネリングサービスが実行され、将来のチャットボットのパブリック URL が完成しました。

ステップ 4. Space にチャットボットを登録する

Space とチャットボットが相互に通信できるようにするには、ボットを Space に登録する必要があります。

アプリケーションを開発するときは、次の 2 つの重要なことを決定する必要があります。

  • アプリケーションのディストリビューション :

    • 単一組織アプリケーションは、単一の Space 組織のみを対象としています。Space ユーザーは、Space UI で単一組織アプリケーションを手動で登録および構成します。

    • 複数組織のアプリケーションは複数の Space 組織を対象としています。複数組織アプリケーションは、API 呼び出しを使用して、特定の Space インスタンスに自身を登録し、構成します。

    練習しているだけなので、複数組織アプリケーションの構成の複雑さに気を取られても意味がありません。代わりに、Space UI を使用してアプリケーションを登録し、構成します。そこで、単一組織アプリケーションを作成します。

  • 認可主体 : アプリケーションが Space 内でどのように動作するかを決定します。アプリケーション自体に代わって、特定の Space ユーザーに代わって、またはその両方で動作します。これにより、アプリケーションがどの認証フローを使用するかが決まります。

    この例では、チャットボットは自分自身に代わって、独自のチャットチャネルで通知を送信します。OAuth 2.0 フローとして、クライアント資格情報フローを使用します。これにより、アプリケーションはクライアント ID とクライアントシークレットを使用して Space で認証できるようになります。

要約すると、私たちのチャットボットは、クライアント資格情報認証フローを使用する単一組織アプリケーションです。それでは、ボットを Space に登録しましょう。

  1. Space インスタンスを開きます。

  2. メインメニューで、「 Extensions 拡張」をクリックし、「インストール済み」を選択します。

  3. 新しいアプリをクリックします。

  4. アプリケーションに一意の名前 (remind-me-bot など) を付け、「作成」をクリックします。

  5. 概要タブで、チャットボットを選択します。これにより、アプリケーションのチャットチャネルが有効になります。

  6. 許可」タブを開きます。このボットはシンプルであり、Space からデータを取得しないため、このタブでは何も変更しません。

    このタブは、それがいかに重要であるかを示すためだけに表示されています。アプリがさまざまな Space モジュールにアクセスする必要がある場合は、対応するアクセス許可を提供する必要があります。権限のリクエストについて詳しくは、こちらを参照します

    Requested permissions
  7. 認証」タブを開きます。クライアント資格情報フローはデフォルトですべてのアプリケーションに対して有効になっていることに注意してください。アプリケーションのクライアント ID およびクライアントシークレットを取得する必要があります。私たちのチャットボットはそれらを使用して Space アクセストークンを取得します。

    Authentications
  8. ユーザーがチャットボットチャネルに何かを入力すると、Space はユーザー入力をアプリケーションに送信します。次のステップは、アプリケーションエンドポイントの URL を指定し、Space からのリクエストを検証する方法を選択することです。

    エンドポイントタブを開きます。

    エンドポイント URI で、ボットのトンネリングサービスによって生成されたパブリック URL を指定します。このエンドポイントの汎用性を低くし、URL に接尾辞 (例: api/space) を追加しましょう。最終エンドポイントは https://{random_string_from_ngrok}.ngrok.io/api/space になります。

    デフォルトでは、Space は公開鍵検証方法を使用することを推奨します。デフォルトのままにして、「保存」をクリックします。

    Endpoint
  9. よくやった ! これで、ボットが Space に登録され、必要な認証データがすべて揃ったため、ボットの開発を開始する準備が整いました。

ステップ 5. Space クライアントを作成する

すべての準備ステップが完了しました。コーディングを行ってみましょう。まず、Space インスタンスにリクエストを送信できる Space クライアントの作成から始める必要があります。

  1. Client.kt ファイルをプロジェクトに追加します。

  2. コードを Client.kt ファイルに追加します。

    package org.remindme import space.jetbrains.api.runtime.SpaceAppInstance import space.jetbrains.api.runtime.SpaceAuth import space.jetbrains.api.runtime.SpaceClient import space.jetbrains.api.runtime.ktorClientForSpace import space.jetbrains.api.runtime.resources.chats import space.jetbrains.api.runtime.types.ChannelIdentifier import space.jetbrains.api.runtime.types.ChatMessage import space.jetbrains.api.runtime.types.ProfileIdentifier // describes connection to a Space instance val spaceAppInstance = SpaceAppInstance( // Copy-paste the client-id, and the client-secret // your app got from Space. clientId = "client-id-assigned-to-app", clientSecret = "client-secret-assigned-to-app", // URL of your Space instance spaceServerUrl = "https://mycompany.jetbrains.space" ) private val spaceHttpClient = ktorClientForSpace() // The Space client is used to call Space API methods. // The application uses the Client Credentials OAuth flow (see [SpaceAuth.ClientCredentials]) // to authorize on behalf of itself. val spaceClient = SpaceClient(ktorClient = spaceHttpClient, appInstance = spaceAppInstance, auth = SpaceAuth.ClientCredentials()) // Get user by ID and send 'message' to the user. // 'spaceClient' gives you access to any Space endpoint. suspend fun sendMessage(userId: String, message: ChatMessage) { spaceClient.chats.messages.sendMessage( channel = ChannelIdentifier.Profile(ProfileIdentifier.Id(userId)), content = message ) }
    注:

    • sendMessage(userId: String, message: ChatMessage) はクライアントを使用してメッセージを Space に送信します。それをさらに拡張してみましょう:

      • userId は、アプリケーションにメッセージを送信し、返信したいユーザーの ID です。

      • ChatMessage は、チャットメッセージを記述する API クラスです。重要なのは、メッセージは単なるテキストではないということです。複雑なフォーマットや、ボタンなどの UI 要素も含めることができます。このようなメッセージの作成を簡素化するために、API クライアントは特別な DSL (メッセージコンストラクター) を提供します。次のステップで見ていきます。

      • spaceClient.chats.messages.sendMessage() – Chats サブシステムをどのように参照するかを参照してください。SpaceHttpClient クラスの最も優れた点は、任意の Space モジュールにアクセスできることです。メンバーのプロファイルを取得したい場合は、チームディレクトリに呼び出しを行うことができます。

        spaceClient.teamDirectory.profiles.getProfile(ProfileIdentifier.Username("John.Doe"))

        クライアント経由でアクセスできるモジュールのリストを表示するには、API Playground を開きます。ここのトップレベルのタイトルは、アクセスできるモジュールです。

        API Playground

        IDE でコード補完を使用することもできます。spaceClient. と入力して候補を調べましょう。

  3. 終わり ! これでクライアントができたため、次に進んでチャットボットの最初のコマンドを作成できます。

ステップ 6. 最初のコマンドを作成する

まずは簡単なことから始めましょう。チャットボットの使用方法のヒントを表示する help コマンドです。

  1. CommandHelp.kt ファイルを作成し、次のコードを追加します。

    package org.remindme import space.jetbrains.api.runtime.helpers.message import space.jetbrains.api.runtime.types.ApiIcon import space.jetbrains.api.runtime.types.ChatMessage import space.jetbrains.api.runtime.types.MessageOutline import space.jetbrains.api.runtime.types.MessageStyle // command for showing chatbot help suspend fun runHelpCommand(payload: MessagePayload) { // get user ID from the payload and send them a help message sendMessage(payload.userId, helpMessage()) } // build the help message using the special DSL fun helpMessage(): ChatMessage { return message { section { text("Soon the help will be shown here!") } } }
  2. 良い ! これで、ユーザーが実際に動作を試せるコマンドができました。

ステップ 7. エンドポイントを定義する

次のステップは、コード内にボットのエンドポイントを作成することです。この手順を完了すると、最終的にボットにコマンドを送信できるようになります。

これは Ktor チュートリアルではないため、Ktor の詳細については詳しく説明しません。Ktor に慣れていない場合は、この素晴らしいフレームワークを知る良い機会になります。Ktor 構文がいかに簡潔であるかに注目してください。

  1. チャットボットはクライアントアプリケーションであるだけでなく、サーバーでもあります。Space からのリクエストをリッスンして処理する必要があります。この目的のために、Ktor はルーティング機能(英語)を提供します。この機能を使用して、/api/space エンドポイントで POST リクエストを処理してみましょう。

    Routes.kt ファイルを作成し、次のコードを追加します。

    package org.remindme import com.fasterxml.jackson.databind.ObjectMapper import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.coroutines.launch import space.jetbrains.api.ExperimentalSpaceSdkApi import space.jetbrains.api.runtime.helpers.command import space.jetbrains.api.runtime.helpers.readPayload import space.jetbrains.api.runtime.helpers.verifyWithPublicKey import space.jetbrains.api.runtime.types.ListCommandsPayload import space.jetbrains.api.runtime.types.MessagePayload fun Application.configureRouting() { routing { post("api/space") { // read request body val body = call.receiveText() // read headers required for Space verification val signature = call.request.header("X-Space-Public-Key-Signature") val timestamp = call.request.header("X-Space-Timestamp")?.toLongOrNull() // verifyWithPublicKey gets a key from Space, uses it to generate message hash // and compares the generated hash to the hash in a message if (signature.isNullOrBlank() || timestamp == null || !spaceClient.verifyWithPublicKey( body, timestamp, signature ) ) { call.respond(HttpStatusCode.Unauthorized) return@post } // analyze the message payload // MessagePayload = user sends a command // ListCommandsPayload = user types a slash or a char when (val payload = readPayload(body)) { is MessagePayload -> { runHelpCommand(payload) call.respond(HttpStatusCode.OK, "") } is ListCommandsPayload -> { } } } } }

    ここで何が起こっているのか:

    • Application.configureRouting() は、Ktor ルーティング機能を構成します。

    • spaceClient.verifyWithPublicKey() は、クライアントがリクエストを受信する Space インスタンスを検証します。Space からの公開鍵を使用してメッセージハッシュを計算し、メッセージヘッダーで送信されたハッシュと比較します。仕組みの詳細については、こちらを参照してください。このチュートリアルでは、リクエストを自分で処理して検証します。あるいは、この目的のために Space.processPayload() ヘルパーメソッドを使用することもできます。この場合、リクエストの検証を実装する必要はありません。

    • readPayload(body: String) は、Space から JSON データを受信し、それを ApplicationPayload に逆シリアル化する SDK ヘルパー関数です。例: この場合、Space からの生データは次のようになります。

      { "className": "MessagePayload", "message": { "className": "MessageContext", "messageId": "JxT000JxT", "channelId": "31m0WE41iCBP", "body": { "className": "ChatMessage.Text", "text": "help" }, "createdTime": "2020-11-08T21:34:24.919Z" }, "accessToken": "", "verificationToken": "85e23ff", "userId": "1eAeu31CZA" }
    • 最も興味深いのは、ペイロードのタイプを分析することです。Space SDK にはいくつかのペイロードタイプがありますが、このチュートリアルでは、そのうちの 2 つにのみ焦点を当てます。

      • MessagePayload : コマンドとコマンド引数を含む標準ペイロード。実際、ボットはユーザーがメッセージを送信するたびに MessagePayload を受信します。

      • ListCommandsPayload : ユーザーが / スラッシュボタンを押すと、ボットはこのペイロードを受信します。ボットは、使用可能なコマンドのリストで応答する必要があります。

    • MessagePayload を受信したら、HTTP コード (この場合は 200 OK) で応答することが重要です。それ以外の場合、ユーザーは 500 Internal Server Error を取得します。

  2. Application.ktmain() アプリケーション関数がルーティングを有効にしてサーバーを起動することを確認します。

    fun main() { embeddedServer(Netty, port = 8080) { configureRouting() }.start(wait = true) }
  3. 終わり ! これで、機能するコマンドが完成しました。ボットを初めて起動する準備が整いました。

ステップ 8. ボットを実行する

  1. Application.kt ファイルを開きます。

  2. Application.ktmain 関数の横にあるガターの Run をクリックして、アプリケーションを起動します。

    Run Ktor server
  3. Space インスタンスを開いてボットを見つけます。Ctrl+K を押してその名前を入力します。

    Find the bot
  4. コードを調べてみると、ユーザーが送信したコマンドをまったく分析していないことがわかります。どのようなリクエストにも helpMessage で応答します。ボットをテストするには、チャットに何かを入力します。次のヘルプメッセージが表示されるはずです。

    Send command to bot
  5. 効いてるよ ! 次に、残りのボット機能を追加しましょう。

ステップ 9. スラッシュコマンドのサポートを追加

ボットを完全に機能できるようにしましょう。

  • チャットボットとみなされるためには、アプリケーションは、ユーザーがチャット内で / スラッシュを押したときに、使用可能なコマンドのリストで応答できなければなりません。この場合、ボットは ListCommandsPayload タイプのペイロードを受信します。

  • ボットはリマインドミーボットと呼ばれているため、タイマーを開始し、タイマーが終了したらユーザーに通知を送信する何らかの remind コマンドが必要です。

  1. Commands.kt ファイルを作成します。

    package org.remindme import space.jetbrains.api.runtime.types.* class ApplicationCommand( val name: String, val info: String, val run: suspend (payload: MessagePayload) -> Unit ) { /** * [CommandDetail] is returned to Space with info about the command. * List of commands is shown to the user. */ fun toSpaceCommand() = CommandDetail(name, info) } // list of available commands val supportedCommands = listOf( ApplicationCommand( "help", "Show this help", ) { payload -> runHelpCommand(payload) }, ApplicationCommand( "remind", "Remind me about something in N seconds, e.g., " + "to remind about \"the thing\" in 10 seconds, send 'remind 10 the thing' ", ) { payload -> runRemindCommand(payload) } ) /** * Response to [ListCommandsPayload]. * Space will display the returned commands as commands supported by your app. */ fun getSupportedCommands() = Commands( supportedCommands.map { it.toSpaceCommand() } )

    ここに:

    • ApplicationCommand クラスはチャットボットコマンドを記述します。ユーザーが name という名前のコマンドをチャットボットに送信すると、ボットはコマンドの run 機能を実行します。

      このコマンドは、CommandDetail (コマンド名と説明) を返す toSpaceCommand 関数を実装する必要があることに注意してください。

    • ボットが ListCommandsPayload を受信すると、getSupportedCommands() 関数は CommandDetail のマップを返します。

  2. CommandRemind.kt ファイルを作成します。

    package org.remindme import kotlinx.coroutines.delay import space.jetbrains.api.runtime.helpers.commandArguments import space.jetbrains.api.runtime.helpers.message import space.jetbrains.api.runtime.types.* suspend fun runRemindCommand(payload: MessagePayload) { val remindMeArgs = getArgs(payload) ?: run { sendMessage(payload.userId, helpMessage()) return } remindAfterDelay(payload.userId, remindMeArgs) } private suspend fun remindAfterDelay(userId: String, remindMeArgs: RemindMeArgs) { sendMessage(userId, acceptRemindMessage(remindMeArgs)) delay(remindMeArgs.delayMs) sendMessage(userId, remindMessage(remindMeArgs)) } private fun acceptRemindMessage(remindMeArgs: RemindMeArgs): ChatMessage { return message { outline( MessageOutline( icon = ApiIcon("checkbox-checked"), text = "Reminder accepted" ) ) section { text("I will remind you in ${remindMeArgs.delayMs / 1000} seconds about \"${remindMeArgs.reminderText}\"") } } } private fun remindMessage(remindMeArgs: RemindMeArgs): ChatMessage { return message { outline( MessageOutline( icon = ApiIcon("clock"), text = "Reminder" ) ) section { text(remindMeArgs.reminderText) text( size = MessageTextSize.SMALL, content = "${remindMeArgs.delayMs / 1000} seconds have passed" ) } } } private fun getArgs(payload: MessagePayload): RemindMeArgs? { val args = payload.commandArguments() ?: return null val delayMs = args.substringBefore(" ").toLongOrNull()?.times(1000) ?: return null val reminderText = args.substringAfter(" ").trimStart().takeIf { it.isNotEmpty() } ?: return null return RemindMeArgs(delayMs, reminderText) } private class RemindMeArgs( val delayMs: Long, val reminderText: String, )

    ここに:

    • runRemindCommand は、指定された時間タイマーを実行します。getArgs() は、remind コマンドの引数 (時刻とテキスト) を取得します。ユーザーが remind 10 some text と入力すると、引数は 10some text になります。

    • remindAfterDelay()acceptRemindMessage をユーザーに送り返し、タイマーが終了すると remindMessage を送信します。

    • acceptRemindMessage および remindMessage は、メッセージビルダー DSL を使用して ChatMessage を作成します。MessageOutline は、メインのメッセージ本文に先行する小さなブロックです。ApiIcon は、メッセージの前に表示されるアイコンイメージを返します。

  3. CommandHelp.kt ファイルを編集します。

    package org.remindme import space.jetbrains.api.runtime.helpers.message import space.jetbrains.api.runtime.types.ApiIcon import space.jetbrains.api.runtime.types.ChatMessage import space.jetbrains.api.runtime.types.MessageOutline import space.jetbrains.api.runtime.types.MessageStyle suspend fun runHelpCommand(payload: MessagePayload) { sendMessage(payload.userId, helpMessage()) } fun helpMessage(): ChatMessage { return message { MessageOutline( icon = ApiIcon("checkbox-checked"), text = "Remind me bot help" ) section { text("List of available commands", MessageStyle.PRIMARY) fields { supportedCommands.forEach { field(it.name, it.info) } } } } }

    ここでは、helpMessage を更新して、supportedCommands のリストを返すようにしました。

  4. Routes.kt ファイルを編集します。

    package org.remindme import com.fasterxml.jackson.databind.ObjectMapper import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.coroutines.launch import space.jetbrains.api.runtime.helpers.command import space.jetbrains.api.runtime.helpers.readPayload import space.jetbrains.api.runtime.helpers.verifyWithPublicKey import space.jetbrains.api.runtime.types.ListCommandsPayload import space.jetbrains.api.runtime.types.MessagePayload fun Routing.api() { post("api/space") { // read request body val body = call.receiveText() // verify if the request comes from a trusted Space instance val signature = call.request.header("X-Space-Public-Key-Signature") val timestamp = call.request.header("X-Space-Timestamp")?.toLongOrNull() // verifyWithPublicKey gets a key from Space, uses it to generate message hash // and compares the generated hash to the hash in a message if (signature.isNullOrBlank() || timestamp == null || !spaceClient.verifyWithPublicKey(body, timestamp, signature) ) { call.respond(HttpStatusCode.Unauthorized) return@post } when (val payload = readPayload(body)) { is ListCommandsPayload -> { // Space requests the list of supported commands call.respondText( // JSON serializer ObjectMapper().writeValueAsString(getSupportedCommands()), ContentType.Application.Json ) } is MessagePayload -> { // user sent a message to the application val commandName = payload.command() val command = supportedCommands.find { it.name == commandName } if (command == null) { runHelpCommand(payload) } else { launch { command.run(payload) } } call.respond(HttpStatusCode.OK, "") } } } }

    ここで変更した点:

    • ボットが ListCommandsPayload (ユーザーが / スラッシュを入力) を受信すると、コマンドのリストで応答するようになりました。ObjectMapper() を使用してリストを JSON に変換することに注意してください。

    • MessagePayload を分析して、使用可能なコマンドのリストから要求されたコマンドを見つけようとします。

  5. もう一度ボットを実行して、ボットのすべての機能を試してみましょう。

    • スラッシュを入力します:

      Slash command
    • help コマンド:

      Slash commands
    • remind コマンド:

      Remind command

よくやった ! シンプルなボットの作成が完了しました。次のチュートリアルでは、チャットボットメッセージに UI 要素を追加する方法を学びます。

関連ページ:

Space SDK

Space SDK は、JetBrains Space HTTP API を操作できるようにし、Space アプリケーションの開発を簡素化するライブラリです。クイックスタート:1. プロジェクト内の Space SDK を参照する次の依存関係をプロジェクトの / ファイルに追加します。// the example is given for build.gradle.kts repositories { // here go other project repos ... maven(...

アプリケーションの開発

アプリケーションは、Space の機能を拡張する主な方法です。アプリケーションは、以下を通じて Space と対話できる外部サーバー側サービスまたはクライアント側プログラム (JavaScript、デスクトップ、モバイル) です。Space SDK、Space HTTP API、Space とアプリケーション間のインタラクション:空間とアプリケーションは双方向で通信できます。アプリケーションはデータを Space に送信できます。例: チャットチャネルにメッセージを送信し、プロジェクトやチーム...

Space HTTP API

Space HTTP API を使用すると、チャット、チームディレクトリ、プロジェクト、ドキュメント、パッケージなどの任意の Space モジュールにプログラムでアクセスできます。特定の API リクエストの実行の詳細については、API 参照を参照するか、API Playground(下記を参照) を使用してください。HTTP API をすぐに使い始めるには、Space SDK を使用します。API Playground:API Playground を使用すると、次のことが可能になります。Spac...

Space での認証

Space のセキュリティは、アクセストークン、つまり API リクエストの認証に使用されるシークレットに基づいています。Space と通信するには、アプリケーションはまずアクセストークンを取得する必要があります。その後、このトークンを使用してリクエストを Space に送信できます。例:GET https://mycompany.jetbrains.space/api/http/absences Authorization: Bearer <here-goes-access-token&...

クライアント資格情報フロー

基本:アプリケーション自体に代わって承認を行います。チャットボットなど、自分自身に代わってアクションを実行するサーバー側アプリケーションに適しています。クライアント資格情報フローでは、アプリケーションはおよびを送信することで Space からアクセストークンを受け取ります。アプリケーションで Space SDK を使用する場合は、メソッドを利用してフローを実装できます。クライアント資格情報フローを使用してすべての操作にアクセスできるわけではありません。多くのアクション (記事の下書きの投稿など...

権限のリクエスト

特定の Space エンドポイントにアクセスするには、アプリケーションはまず対応するアクセス許可を取得する必要があります。例: アプリケーションがプロジェクトの課題を作成する場合、アプリケーションには課題の作成権限が必要です。課題の詳細を表示するには、課題を表示する権限が必要です。アプリケーションに必要な権限のセット全体は、権限スコープと呼ばれます。アプリケーションがアクセス許可を要求する方法は、アプリケーション自体の代わりに動作するアプリケーションと、Space ユーザーの代わりに動作するアプ...