### Install Project Dependencies Source: https://github.com/wireapp/integration-docs/blob/main/README.md Run this command to install all necessary project dependencies. ```bash npm ci ``` -------------------------------- ### Start Local Development Server Source: https://github.com/wireapp/integration-docs/blob/main/README.md Starts a local development server with hot reload for live previewing of changes. The site will be available at http://localhost:3000. ```bash npm start ``` -------------------------------- ### Initialize WireApp SDK and Handle Text Messages (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Initializes the WireApp SDK with application credentials and a handler for incoming text messages. Ensure your cryptography key is 32 bytes long. The SDK starts listening for events automatically. ```kotlin fun main() { val wireAppSdk = WireAppSdk( applicationId = UUID.fromString("YOUR_APPLICATION_ID"), apiToken = "YOUR_API_TOKEN", apiHost = "YOUR_API_HOST", cryptographyStorageKey = "yourGeneratedSecureKeyByteArray!".encodeToByteArray(), // Must be 32 bytes object : WireEventsHandlerSuspending() { override suspend fun onTextMessageReceived(wireMessage: WireMessage.Text) { println("Text message received: $wireMessage") // Add your message handling logic here, like storing the message, // sending back another message, or triggering some workflow } } ) // Start the SDK wireAppSdk.startListening() } ``` -------------------------------- ### Initialize WireApp SDK and Handle Text Messages (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Initializes the WireApp SDK with application credentials and a handler for incoming text messages. The SDK starts listening for events automatically. Use `WireEventsHandlerDefault` for Java implementations. ```java public class Main { public static void main(String[] args) { final var wireAppSdk = new WireAppSdk( UUID.fromString("YOUR_APPLICATION_ID"), "YOUR_API_TOKEN", "YOUR_API_HOST", "yourGeneratedSecureKeyByteArray!".getBytes(), new WireEventsHandlerDefault() { @Override public void onTextMessageReceived(@NotNull WireMessage.Text wireMessage) { System.out.println("Text message received: $wireMessage"); // Add your message handling logic here, like storing the message, // sending back another message, or triggering some workflow } } ); // Start the SDK wireAppSdk.startListening(); } } ``` -------------------------------- ### Get all members of a conversation Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/07-list-conversation-members.mdx This example demonstrates how to retrieve all members of a specific conversation and iterate through them to display their user ID and role. ```APIDOC ## Get all members of a conversation ### Description Retrieves all members of a conversation. ### Method `WireApplicationManager.getStoredConversationMembers` ### Parameters #### Path Parameters - **conversationId** (`QualifiedId`) - Required - The ID of the conversation. ### Response #### Success Response (List) - **userId** (`QualifiedId`) - The `QualifiedId` of the member. - **role** (`ConversationRole`) - The member's `ConversationRole` (ADMIN or MEMBER). ### Request Example (Kotlin) ```kotlin val applicationManager = wireAppSdk.getApplicationManager() val myConversationId = QualifiedId( id = UUID.fromString("conversation-id"), domain = "conversation-domain.com" ) val members: List = applicationManager.getStoredConversationMembers( conversationId = myConversationId ) members.forEach { member -> println("User: ${member.userId}, Role: ${member.role}") } ``` ### Request Example (Java) ```java WireApplicationManager applicationManager = wireAppSdk.getApplicationManager(); QualifiedId myConversationId = new QualifiedId( UUID.fromString("conversation-id"), "conversation-domain.com" ); List members = applicationManager.getStoredConversationMembers( myConversationId ); for (ConversationMember member : members) { System.out.println("User: " + member.userId() + ", Role: " + member.role()); } ``` ``` -------------------------------- ### Get User Info by QualifiedId (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/10-get-user-info.mdx Retrieve a user's details using their QualifiedId. Requires an instance of WireApplicationManager. ```java WireApplicationManager applicationManager = wireAppSdk.getApplicationManager(); QualifiedId userId = new QualifiedId( UUID.fromString("user-id"), "user-domain.com" ); UserResponse user = applicationManager.getUser(userId); System.out.println("Display name: " + user.name()); System.out.println("Handle: @" + user.handle()); ``` -------------------------------- ### Get User Info by QualifiedId (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/10-get-user-info.mdx Retrieve a user's details using their QualifiedId. Requires an instance of WireApplicationManager. ```kotlin val applicationManager = wireAppSdk.getApplicationManager() val userId = QualifiedId( id = UUID.fromString("user-id"), domain = "user-domain.com" ) val user: UserResponse = applicationManager.getUserSuspending(userId) println("Display name: ${user.name}") println("Handle: @${user.handle}") ``` -------------------------------- ### Get User Information Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/10-get-user-info.mdx Retrieve a `UserResponse` object containing detailed user information by providing their `QualifiedId`. ```APIDOC ## getUser ### Description Retrieves user information based on their `QualifiedId`. ### Method `getUserSuspending` (Kotlin) / `getUser` (Java) ### Parameters #### Path Parameters - **userId** (QualifiedId) - Required - The unique identifier of the user. ### Response #### Success Response (200) - **id** (QualifiedId) - The user's `QualifiedId`. - **name** (string) - The user's display name. - **handle** (string) - The user's unique handle (username). - **email** (string) - The user's email address (if available). - **teamId** (string) - The UUID of the team the user belongs to (if any). - **accentId** (integer) - The user's accent color ID. - **supportedProtocols** (List) - List of cryptographic protocols supported by the user. - **deleted** (boolean) - Whether the user has been deleted. ### Request Example ```kotlin val userId = QualifiedId( id = UUID.fromString("user-id"), domain = "user-domain.com" ) val user: UserResponse = applicationManager.getUserSuspending(userId) ``` ### Response Example ```json { "id": { "id": "user-id", "domain": "user-domain.com" }, "name": "John Doe", "handle": "johndoe", "email": "john.doe@example.com", "teamId": "team-uuid", "accentId": 1, "supportedProtocols": ["protocol1", "protocol2"], "deleted": false } ``` ``` -------------------------------- ### Custom WireEventsHandler Implementation (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Defines a separate class for handling Wire events, which is useful for complex event management. This example shows how to log received text messages. ```kotlin class MyWireEventsHandler : WireEventsHandlerSuspending() { private val logger = LoggerFactory.getLogger(MyWireEventsHandler::class.java) override suspend fun onTextMessageReceived(wireMessage: WireMessage.Text) { logger.info("Text message received: $wireMessage") } } ``` -------------------------------- ### Get All Conversation Members (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/07-list-conversation-members.mdx Retrieves all members of a specified conversation. Requires an instance of WireApplicationManager and a QualifiedId for the conversation. ```java WireApplicationManager applicationManager = wireAppSdk.getApplicationManager(); QualifiedId myConversationId = new QualifiedId( UUID.fromString("conversation-id"), "conversation-domain.com" ); List members = applicationManager.getStoredConversationMembers( myConversationId ); // Iterate through members for (ConversationMember member : members) { System.out.println("User: " + member.userId() + ", Role: " + member.role()); } ``` -------------------------------- ### Get All Conversation Members (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/07-list-conversation-members.mdx Retrieves all members of a specified conversation. Requires an instance of WireApplicationManager and a QualifiedId for the conversation. ```kotlin val applicationManager = wireAppSdk.getApplicationManager() val myConversationId = QualifiedId( id = UUID.fromString("conversation-id"), domain = "conversation-domain.com" ) val members: List = applicationManager.getStoredConversationMembers( conversationId = myConversationId ) // Iterate through members members.forEach { member -> println("User: ${member.userId}, Role: ${member.role}") } ``` -------------------------------- ### Custom WireEventsHandler Implementation (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Defines a separate class for handling Wire events in Java, extending `WireEventsHandlerDefault`. This example logs received text messages using SLF4J. ```java public class MyWireEventsHandler extends WireEventsHandlerDefault { private static final Logger logger = LoggerFactory.getLogger(MyWireEventsHandler.class); @Override public void onTextMessageReceived(@NotNull WireMessage.Text wireMessage) { logger.info("Text message received: $wireMessage"); } } ``` -------------------------------- ### Build Wire SDK Locally Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Run this Gradle command to build the SDK locally, skipping the signing option. Ensure 'mavenCentral()' is included in your app's build.gradle.kts if using the locally built SDK. ```bash ./gradlew publishToMavenLocal -PskipSigning=true ``` -------------------------------- ### Filter admins from a conversation Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/07-list-conversation-members.mdx This example shows how to filter the list of conversation members to only include those with the ADMIN role. ```APIDOC ## Filter admins from a conversation ### Description Filters a list of conversation members to return only those with the ADMIN role. ### Method `WireApplicationManager.getStoredConversationMembers` (used in conjunction with filtering logic) ### Parameters #### Path Parameters - **conversationId** (`QualifiedId`) - Required - The ID of the conversation. ### Response #### Success Response (List) - **userId** (`QualifiedId`) - The `QualifiedId` of the member. - **role** (`ConversationRole`) - The member's `ConversationRole` (ADMIN or MEMBER). ### Request Example (Kotlin) ```kotlin val admins = applicationManager.getStoredConversationMembers(myConversationId) .filter { it.role == ConversationRole.ADMIN } ``` ### Request Example (Java) ```java List admins = applicationManager.getStoredConversationMembers(myConversationId) .stream() .filter(member -> member.role() == ConversationRole.ADMIN) .toList(); ``` ``` -------------------------------- ### Generate Static Content Source: https://github.com/wireapp/integration-docs/blob/main/README.md Use this command to generate the static content for the documentation site. ```bash npm run build ``` -------------------------------- ### Create Simple Echo App (Main.kt) Source: https://github.com/wireapp/integration-docs/blob/main/docs/02-manage-apps/00-demo.mdx This Kotlin code defines a basic echo bot using the Wire Apps SDK. It initializes the SDK with application details and handles incoming text messages by echoing them back. ```kotlin import com.wire.sdk.WireAppSdk import com.wire.sdk.WireEventsHandlerSuspending import com.wire.sdk.model.WireMessage import java.util.UUID fun main() { val wireAppSdk = WireAppSdk( applicationId = UUID.fromString("YOUR_APPLICATION_ID"), apiToken = "YOUR_API_TOKEN", apiHost = "YOUR_API_HOST", cryptographyStorageKey = "yourGeneratedSecureKeyByteArray!".encodeToByteArray(), // Must be 32 bytes, wireEventsHandler = SampleEventsHandler() ) wireAppSdk.startListening() } class SampleEventsHandler : WireEventsHandlerSuspending() { override suspend fun onMessage(wireMessage: WireMessage.Text) { val message = WireMessage.Text.createReply( text = "echoing ${wireMessage.text}", originalMessage = wireMessage, mentions = wireMessage.mentions ) manager.sendMessage(message) } } ``` -------------------------------- ### Send Welcome Message in Java Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/03-on-app-added-to-conversation.mdx This Java snippet demonstrates how to send a welcome message upon the app's addition to a conversation. It creates a text message and sends it via the manager. ```java @Override public void onAppAddedToConversation( @NotNull Conversation conversation, @NotNull List members ) { final WireMessage message = WireMessage.Text.create( conversation.id(), "đŸ‘‹ Hi there! You can use `/remind [text]` to set personal reminders.", List.of(), List.of(), null ); getManager().sendMessage(message); } ``` -------------------------------- ### Get Sender Info from Message (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/10-get-user-info.mdx Fetch the sender's information from a received text message using their QualifiedId. ```java @Override public void onTextMessageReceived(WireMessage.Text message) { UserResponse senderInfo = manager.getUser(message.sender()); System.out.println("Message from " + senderInfo.name() + ": " + message.text()); } ``` -------------------------------- ### Get Sender Info from Message (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/10-get-user-info.mdx Fetch the sender's information from a received text message using their QualifiedId. ```kotlin override suspend fun onTextMessageSuspending(message: WireMessage.Text) { val senderInfo = manager.getUserSuspending(message.sender) println("Message from ${senderInfo.name}: ${message.text}") } ``` -------------------------------- ### Search for a user by name Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/11-search-users.mdx Demonstrates how to search for users by providing a query, domain, and the desired number of results. The results are then iterated to display found user names and handles. ```APIDOC ## Search Users ### Description Searches for Wire users based on a query string, optionally filtering by domain and limiting the number of results. ### Method `searchUsersSuspending` (Kotlin) / `searchUsers` (Java) ### Parameters - **query** (String) - The search term (name or handle). - **domain** (String) - The domain to search within (e.g., "wire.com"). - **numberOfResults** (Int) - The maximum number of results to return. ### Response - **SearchContactsResponse** - An object containing search results. - **documents** (List) - A list of matching user profiles. - **found** (Int) - The total count of users found. ### ContactDocument Details Each `ContactDocument` includes: - **id** (String) - User's UUID. - **qualifiedId** (String) - User's `QualifiedId` (id + domain). - **name** (String) - User's display name. - **handle** (String) - User's unique handle. - **accentId** (String) - User's accent color ID (if available). - **team** (String) - UUID of the user's team (if any). - **type** (String) - Type of user (`regular`, `bot`, `external`, `federated`, `guest`). ### Request Example (Kotlin) ```kotlin val applicationManager = wireAppSdk.getApplicationManager() val results: SearchContactsResponse = applicationManager.searchUsersSuspending( query = "Alice", domain = "wire.com", numberOfResults = 25 ) results.documents.forEach { contact -> println("Found: ${contact.name} (@${contact.handle})") } ``` ### Request Example (Java) ```java WireApplicationManager applicationManager = wireAppSdk.getApplicationManager(); SearchContactsResponse results = applicationManager.searchUsers( "Alice", "wire.com", 25 ); for (ContactDocument contact : results.getDocuments()) { System.out.println("Found: " + contact.name() + " (@" + contact.handle() + ")"); } ``` ### About Search Results Search queries are normalized (lowercase, diacritics removed) before matching. Results are prioritized by: 1. Exact handle match. 2. Exact display name match. 3. Handle starts with query. 4. Display name starts with query. ``` -------------------------------- ### Configure Gradle Build File (build.gradle.kts) Source: https://github.com/wireapp/integration-docs/blob/main/docs/02-manage-apps/00-demo.mdx This snippet configures the Gradle build for a Kotlin project, specifying the Kotlin version, repositories, SDK dependency, and JVM toolchain. ```kotlin plugins { kotlin("jvm") version "2.3.10" } group = "org.example" version = "1.0-SNAPSHOT" repositories { mavenCentral() } dependencies { implementation("com.wire:wire-apps-jvm-sdk:0.1.0") } tasks.test { useJUnitPlatform() } kotlin { jvmToolchain(17) } ``` -------------------------------- ### Send Welcome Message in Kotlin Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/03-on-app-added-to-conversation.mdx Use this snippet to send a welcome message to a conversation when the app is added. It constructs a text message and sends it using the manager. ```kotlin override suspend fun onAppAddedToConversation( conversation: Conversation, members: List ) { val message = WireMessage.Text.create( conversationId = conversation.id, text = "đŸ‘‹ Hi there! You can use `/remind [text]` to set personal reminders." ) manager.sendMessageSuspending(message = message) } ``` -------------------------------- ### Greeting New Joiners in Kotlin Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/15-on-user-joined-conversation.mdx Use this Kotlin snippet to send a welcome message to new members joining a conversation. It retrieves user details and constructs a greeting message before sending it. ```kotlin override suspend fun onUserJoinedConversation( conversationId: QualifiedId, members: List ) { val users = members.map { manager.getUserSuspending(it.userId) } val welcomeText = buildString { append("Welcome ") append(users.joinToString(" and ") { it.name }) append("!") } val message = WireMessage.Text.create( conversationId = conversationId, text = welcomeText ) manager.sendMessageSuspending(message) } ``` -------------------------------- ### Create Group, One-to-One, and Channel Conversations (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/03-create-conversation.md Use the WireApplicationManager to create group, one-to-one, and channel conversations. For group and channel conversations, provide a name and a list of user IDs. For one-to-one conversations, specify the target user ID. Channel conversations also require a team ID. ```kotlin val applicationManager = wireAppSdk.getApplicationManager() // For Group Conversations there is no need to pass the App user ID as it will be added to the conversation by default. val createdGroupConversationId = applicationManager.createGroupConversationSuspending( name = "Conversation Name", userIds = listOf( QualifiedId(userId1, userDomain1), QualifiedId(userId2, userDomain2) ) ) // For One to One Conversations you need to pass only the user whom the App will create the One to One conversation with. val createdOneToOneConversationId = applicationManager.createOneToOneConversationSuspending( userId = QualifiedId(otherUserId, otherUserDomain) ) // Channel Conversations are similar to Group Conversations, with the difference of passing the Team ID. val createdChannelConversationId = applicationManager.createChannelConversationSuspending( name = "Channel Name", userIds = listOf( QualifiedId(userId1, userDomain1), QualifiedId(userId2, userDomain2) ), teamId = TeamId(value = UUID.fromString("my-team-id")) ) ``` -------------------------------- ### Search for a user by name (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/11-search-users.mdx Use the `searchUsersSuspending` method to find users by name. Specify the query, domain, and the desired number of results. The results are then iterated to print the found contacts' names and handles. ```kotlin val applicationManager = wireAppSdk.getApplicationManager() val results: SearchContactsResponse = applicationManager.searchUsersSuspending( query = "Alice", domain = "wire.com", numberOfResults = 25 ) results.documents.forEach { contact -> println("Found: ${contact.name} (@${contact.handle})") } ``` -------------------------------- ### Delete Message on Button Click (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/06-on-button-clicked.mdx Implement the `onButtonClicked` function to handle button actions. This example deletes the referenced message if the button with ID 'delete' is clicked. Requires `manager.sendMessageSuspending` for asynchronous message sending. ```kotlin override suspend fun onButtonClicked(wireMessage: WireMessage.ButtonAction) { if (wireMessage.buttonId == "delete") { val delete = WireMessage.Deleted.create( conversationId = wireMessage.conversationId, messageId = wireMessage.referencedMessageId ) manager.sendMessageSuspending(delete) } } ``` -------------------------------- ### Enable DEBUG Logging for Wire SDK Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Set the log level to DEBUG for the 'com.wire.sdk' package in your logging framework, such as Logback, to aid in application development and testing. ```xml ``` -------------------------------- ### Delete Message on Button Click (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/06-on-button-clicked.mdx Implement the `onButtonClicked` method to respond to button clicks. This Java example deletes the composite message if the 'delete' button is pressed. It uses `getManager().sendMessage` to send the deletion request. ```java @Override public void onButtonClicked(@NotNull WireMessage.ButtonAction wireMessage) { if (wireMessage.buttonId().equals("delete")) { WireMessage.Deleted delete = WireMessage.Deleted.create( wireMessage.conversationId(), wireMessage.referencedMessageId() ); getManager().sendMessage(delete); } } ``` -------------------------------- ### Create and Send Composite Message (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/01-send-message.mdx This Java snippet demonstrates how to construct a composite message with a text prompt and a list of buttons, and then send it. The conversationId and applicationManager must be initialized. ```java WireMessage.Composite compositeMessage = WireMessage.Composite.create( conversationId, "What's the best JVM language?", List.of( new WireMessage.Button("Java"), new WireMessage.Button("Kotlin") ) ); applicationManager.sendMessage(compositeMessage); ``` -------------------------------- ### Create and Send Composite Message (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/01-send-message.mdx Use this snippet to create a composite message with text and buttons, then send it asynchronously. Ensure you have the WireMessage and applicationManager objects available. ```kotlin val compositeMessage = WireMessage.Composite.create( conversationId = conversationId, text = "What's the best JVM language?", buttonList = listOf( WireMessage.Button(text = "Java"), WireMessage.Button(text = "Kotlin") ) ) applicationManager.sendMessageSuspending(compositeMessage) ``` -------------------------------- ### Promote Member to Admin (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/08-update-member-role.mdx Use this to promote a member to an administrator role in a conversation. Ensure the conversation is a group or channel and the app has admin permissions. ```java WireApplicationManager applicationManager = wireAppSdk.getApplicationManager(); QualifiedId myConversationId = new QualifiedId( UUID.fromString("conversation-id"), "conversation-domain.com" ); QualifiedId memberToPromote = new QualifiedId( UUID.fromString("member-user-id"), "member-domain.com" ); applicationManager.updateConversationMemberRole( myConversationId, memberToPromote, ConversationRole.ADMIN ); ``` -------------------------------- ### Add Wire SDK to Maven Project Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Add the Wire Apps JVM SDK as a dependency in your Maven project's pom.xml file. Verify the version number. ```xml com.wire wire-apps-jvm-sdk 0.1.0 ``` -------------------------------- ### Search for a user by name (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/11-search-users.mdx Utilize the `searchUsers` method to locate users by name. This method requires the search query, domain, and the maximum number of results. The code iterates through the returned documents to display each contact's name and handle. ```java WireApplicationManager applicationManager = wireAppSdk.getApplicationManager(); SearchContactsResponse results = applicationManager.searchUsers( "Alice", "wire.com", 25 ); for (ContactDocument contact : results.getDocuments()) { System.out.println("Found: " + contact.name() + " (@" + contact.handle() + ")"); } ``` -------------------------------- ### Download Received Asset in Kotlin Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/05-on-asset-message-received.mdx Use `downloadAssetSuspending` with `remoteData` to retrieve the asset's byte array. The asset is then written to a local file. Ensure the output directory exists. ```kotlin override suspend fun onAssetMessageReceived(wireMessage: WireMessage.Asset) { wireMessage.remoteData?.let { remoteData -> val asset = manager.downloadAssetSuspending(remoteData) val fileName = wireMessage.name ?: "unknown" val outputDir = File("build/downloaded_assets").apply { mkdirs() } val outputFile = File(outputDir, fileName) outputFile.writeBytes(asset.value) } } ``` -------------------------------- ### Ping Back in Java Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/07-on-ping-received.mdx Responds to an incoming ping by sending a new ping back to the same conversation. Requires the `manager` to be available. ```java @Override public void onPingReceived(@NotNull WireMessage.Ping wireMessage) { WireMessage.Ping ping = WireMessage.Ping.create( wireMessage.conversationId(), null ); getManager().sendMessage(ping); } ``` -------------------------------- ### Promote Member to Admin (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/08-update-member-role.mdx Use this to promote a member to an administrator role in a conversation. Ensure the conversation is a group or channel and the app has admin permissions. ```kotlin val applicationManager = wireAppSdk.getApplicationManager() val myConversationId = QualifiedId( id = UUID.fromString("conversation-id"), domain = "conversation-domain.com" ) val memberToPromote = QualifiedId( id = UUID.fromString("member-user-id"), domain = "member-domain.com" ) applicationManager.updateConversationMemberRoleSuspending( conversationId = myConversationId, userId = memberToPromote, newRole = ConversationRole.ADMIN ) ``` -------------------------------- ### Send Asset Message Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/01-send-message.mdx Upload and send an asset (file) to a conversation. You must provide the file data, name, and MIME type. ```kotlin // Get local file from resources val filename = "my-file.png" val resourcePath = javaClass.classLoader.getResource(filename)?.path ?: throw IllegalStateException("Resource '$filename' not found") val asset = File(resourcePath) // Read File data in ByteArray val originalData = asset.readBytes() // Send File with necessary parameters applicationManager.sendAssetSuspending( conversationId = conversationId, asset = AssetResource(originalData), name = asset.name, mimeType = "image/png", retention = AssetRetention.ETERNAL ) ``` ```java // Get local file from resources String filename = "my-file.png"; URL resourceUrl = getClass().getClassLoader().getResource(filename); if (resourceUrl == null) { throw new IllegalStateException("Resource '" + filename + "' not found"); } File asset = new File(resourceUrl.getPath()); // Read file into byte[] byte[] originalData; try { originalData = Files.readAllBytes(asset.toPath()); } catch (IOException e) { throw new RuntimeException("Failed to read file: " + asset.getName(), e); } // Send file with necessary parameters applicationManager.sendAsset( conversationId, new AssetResource(originalData), null, asset.getName(), "image/png", AssetRetention.ETERNAL ); ``` -------------------------------- ### Ping Back in Kotlin Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/07-on-ping-received.mdx Responds to an incoming ping by sending a new ping back to the same conversation. Requires the `manager` to be available. ```kotlin override suspend fun onPingReceived(wireMessage: WireMessage.Ping) { val ping = WireMessage.Ping.create( conversationId = wireMessage.conversationId, ) manager.sendMessageSuspending(message = ping) } ``` -------------------------------- ### Download Received Asset in Java Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/05-on-asset-message-received.mdx Retrieve the asset using `downloadAsset` with `remoteData`. The code handles potential null or empty file names and writes the asset to a local file, including basic error handling for file writing. ```java @Override public void onAssetMessageReceived(WireMessage.Asset wireMessage) { WireMessage.Asset.RemoteData remoteData = wireMessage.remoteData(); if (remoteData != null) { byte[] asset = getManager().downloadAsset(remoteData); String fileName = wireMessage.name(); if (fileName == null || fileName.trim().isEmpty()) { fileName = "unknown"; } File outputDir = new File("build/downloaded_assets"); outputDir.mkdirs(); File outputFile = new File(outputDir, fileName); try { Files.write(outputFile.toPath(), asset); } catch (IOException e) { System.out.println("Failed to write asset to file: " + e); } } } ``` -------------------------------- ### Incoming Webhook Sequence Diagram Source: https://github.com/wireapp/integration-docs/blob/main/docs/001-webhook.mdx Depicts the interaction flow when an external system sends a webhook to your application, which then processes it and sends an encrypted message via the Wire SDK. ```mermaid sequenceDiagram participant Ext as External System
(Jira, CI/CD, monitoring…) participant App as Your App
(HTTP server + Wire SDK) participant Wire as Wire Backend Ext->>App: POST /webhook (HTTP) Note over App: Parse and format payload App->>Wire: Send encrypted message (via SDK) Wire-->>App: Confirmation ``` -------------------------------- ### Add Wire SDK to Gradle Project Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Include the Wire Apps JVM SDK dependency in your Gradle build file. Ensure you are using a compatible version. ```kotlin dependencies { implementation("com.wire:wire-apps-jvm-sdk:0.1.0") } ``` -------------------------------- ### Approval Workflow Sequence Diagram Source: https://github.com/wireapp/integration-docs/blob/main/docs/001-webhook.mdx Visualizes the sequence of events in an approval workflow, from an external system requesting approval via webhook to a user's decision triggering the next step. ```mermaid sequenceDiagram participant Ext as External System participant App as Your App participant Wire as Wire participant User as Team member Ext->>App: POST /webhook (approval request) App->>Wire: Send composite message with buttons Wire->>User: Deliver encrypted message User->>Wire: Select button (Approve / Reject) Wire->>App: Button click event (via SDK) App->>Ext: Trigger next workflow step ``` -------------------------------- ### Mermaid Diagram of Wire Architecture Source: https://github.com/wireapp/integration-docs/blob/main/docs/06-architecture.md This diagram illustrates the high-level architecture of Wire, showing the interaction between the Wire Backend, Wire SDK, and Developer Applications. ```mermaid architecture-beta group wireBackend(wire:cloud)[Wire Backend] service webSocketAPI(wire:server)[WebSocket API] in wireBackend service restAPI(wire:server)[REST API] in wireBackend webSocketAPI:R <--> L:eventListener restAPI:R <--> L:restClient group wireSDK(wire:attachment)[Wire SDK] service eventListener(wire:sync)[Events Listener] in wireSDK service restClient(wire:cloud)[REST Client] in wireSDK service crypto(wire:lock)[Crypto Module] in wireSDK junction junctionLeftUp in wireSDK junction junctionLeftMid in wireSDK junction junctionLeftDown in wireSDK restClient:R <-- L:junctionLeftDown eventListener:R -- L:junctionLeftUp junctionLeftDown:T -- B:junctionLeftMid junctionLeftUp:B -- T:junctionLeftMid junctionLeftMid:R --> L:crypto group devInterface(wire:desktop)[Developer Interface] in wireSDK service eventsRouter(wire:siren)[Events Handler] in devInterface service appManager(wire:settings)[Application Manager] in devInterface junction junctionMidUp in wireSDK junction junctionMidDown in wireSDK crypto:T -- B:junctionMidUp junctionMidUp:R --> L:eventsRouter crypto:B <-- T:junctionMidDown junctionMidDown:R -- L:appManager junction devInterfaceJunction in devInterface eventsRouter:B -- T:devInterfaceJunction appManager:T -- B:devInterfaceJunction devInterfaceJunction:R -- L:appLogic group devApp(wire:service)[Developer App] service appLogic(wire:compliant-1)[App Logic] in devApp ``` -------------------------------- ### Mirror User Reaction in Java Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/12-on-message-reaction-received.mdx This Java snippet shows how to mirror a user's reaction to a message. It constructs a new reaction object using the original message and its emoji set, then sends it. The `getManager()` method should be accessible. ```java @Override public void onMessageReactionReceived(@NotNull WireMessage.Reaction wireMessage) { WireMessage.Reaction reaction = WireMessage.Reaction.create( wireMessage wireMessage.getEmojiSet() ); getManager().sendMessage(reaction); } ``` -------------------------------- ### Mirror User Reaction in Kotlin Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/12-on-message-reaction-received.mdx This Kotlin snippet demonstrates how to mirror a user's reaction to a message. It creates a new reaction event with the same emoji set and sends it back. Ensure the `manager` is properly initialized. ```kotlin override suspend fun onMessageReactionReceived(wireMessage: WireMessage.Reaction) { val reaction = WireMessage.Reaction.create( originalMessage = wireMessage emojiSet = wireMessage.emojiSet ) manager.sendMessageSuspending(reaction) } ``` -------------------------------- ### Reply to a message (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/01-send-message.mdx Create and send a reply to an existing message. The original message must implement the `Replyable` interface. Cannot reply to ephemeral messages. ```kotlin val replyMessage = WireMessage.Text.createReply( text = "This is my reply!", originalMessage = originalMessage // The message you're replying to ) applicationManager.sendMessageSuspending(replyMessage) ``` -------------------------------- ### Send Asset Message Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/01-send-message.mdx Upload and send an asset (file) to a conversation. You need to provide the file data, name, and MIME type. ```APIDOC ## Send Asset Message ### Description Uploads and sends an asset (file) to a conversation. Requires file data, name, and MIME type. ### Method `applicationManager.sendAssetSuspending(...)` (Kotlin) `applicationManager.sendAsset(...)` (Java) ### Parameters - `conversationId` (QualifiedId): The ID of the conversation. - `asset` (AssetResource): The asset data. - `name` (String): The name of the asset file. - `mimeType` (String): The MIME type of the asset. - `retention` (AssetRetention): The retention policy for the asset. ### Request Example (Kotlin) ```kotlin val asset = File(resourcePath) val originalData = asset.readBytes() applicationManager.sendAssetSuspending( conversationId = conversationId, asset = AssetResource(originalData), name = asset.name, mimeType = "image/png", retention = AssetRetention.ETERNAL ) ``` ### Request Example (Java) ```java byte[] originalData = Files.readAllBytes(asset.toPath()); applicationManager.sendAsset( conversationId, new AssetResource(originalData), null, asset.getName(), "image/png", AssetRetention.ETERNAL ); ``` ``` -------------------------------- ### Accessing Teams, Conversations, and App Data Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/02-teams-and-conversations.md Retrieve all teams the application is invited to, all accessible conversations, and the application's own data. Ensure the WireAppSDK is initialized before accessing the ApplicationManager. ```kotlin val applicationManager = wireAppSdk.getApplicationManager() // Get all teams the application has been invited to val teams = applicationManager.getStoredTeams() teams.forEach { teamId -> println("Team: $teamId") } // Get all conversations the application has access to val conversations = applicationManager.getStoredConversations() conversations.forEach { conversation -> println("Conversation: ${conversation.id} in team: ${conversation.teamId}") } // Get application data val appData = applicationManager.getApplicationData() println("Application name: ${appData.name}") ``` -------------------------------- ### Reply to a message (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/01-send-message.mdx Create and send a reply to an existing message. The original message must implement the `Replyable` interface. Cannot reply to ephemeral messages. ```java WireMessage replyMessage = WireMessage.Text.createReply( "This is my reply!", List.of(), // mentions List.of(), // linkPreviews originalMessage, // The message you're replying to null // expiresAfterMillis ); applicationManager.sendMessage(replyMessage); ``` -------------------------------- ### Echoing a Received Text Message (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Responds to a received text message by creating a reply that includes the original message text and sender information. The `manager` is used to send the reply back. ```kotlin override suspend fun onTextMessageReceived(wireMessage: WireMessage.Text) { val message = WireMessage.Text.createReply( text = "${wireMessage.text} -- Sent from the SDK", mentions = wireMessage.mentions, originalMessage = wireMessage ) // The manager is accessible through the inherited WireEventsHandler class. // It is used to manage the Wire application's lifecycle and communication with the backend. manager.sendMessageSuspending(message = message) } ``` -------------------------------- ### Demote Admin to Member (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/08-update-member-role.mdx Use this to demote an administrator to a regular member role in a conversation. Ensure the conversation is a group or channel and the app has admin permissions. ```kotlin applicationManager.updateConversationMemberRoleSuspending( conversationId = myConversationId, userId = memberToDemote, newRole = ConversationRole.MEMBER ) ``` -------------------------------- ### Demote Admin to Member (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/08-update-member-role.mdx Use this to demote an administrator to a regular member role in a conversation. Ensure the conversation is a group or channel and the app has admin permissions. ```java applicationManager.updateConversationMemberRole( myConversationId, memberToDemote, ConversationRole.MEMBER ); ``` -------------------------------- ### Calculate Distance from Wire HQ (Kotlin) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/08-on-location-message-received.mdx Calculates the approximate distance in kilometers from the user's received location to Wire's headquarters in Berlin. Sends a reply message with the calculated distance. Requires the `WireMessage.Location` object. ```kotlin override suspend fun onLocationMessageReceived(wireMessage: WireMessage.Location) { // Wire HQ in Berlin val hqLat = 52.5240008 val hqLon = 13.4025010 // User location val lat = wireMessage.latitude val lon = wireMessage.longitude // Simple approximate distance (in km) val latDiff = lat - hqLat val lonDiff = (lon - hqLon) * kotlin.math.cos(Math.toRadians((lat + hqLat) / 2)) val distanceKm = kotlin.math.sqrt(latDiff * latDiff + lonDiff * lonDiff) * 111.0 val message = WireMessage.Text.createReply( text = "You are $distanceKm km away from Wire GmbH headquarters.", originalMessage = wireMessage ) manager.sendMessageSuspending(message = message) } ``` -------------------------------- ### Send Text Message with Mentions Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/01-send-message.mdx Send a text message that includes mentions of specific users. You need to provide the user ID, text, and the offset/length of the mention. ```kotlin val mention = WireMessage.Mention( userId = targetUserId, offset = 0, // Position in text where mention starts length = 5 // Length of the mention text including '@' character ) val textMessage = WireMessage.Text.create( conversationId = conversationId, text = "@John check this out!", mentions = listOf(mention) ) applicationManager.sendMessageSuspending(textMessage) ``` ```java WireMessage.Mention mention = new WireMessage.Mention( targetUserId, 0, // Position in text where mention starts 5 // Length of the mention text including '@' character ); WireMessage textMessage = WireMessage.Text.create( conversationId, "@John check this out!", List.of(mention), List.of(), null ); applicationManager.sendMessage(textMessage); ``` -------------------------------- ### Generate Secure Cryptographic Key Source: https://github.com/wireapp/integration-docs/blob/main/docs/05-secure-integration-guidelines/01-security-privacy-basics.md Generates a cryptographically secure random byte array for use as an encryption key. Ensure the generated key is exactly 32 bytes and is stored securely. ```kotlin import java.security.SecureRandom import java.util.Base64 fun generateSecureKey(length: Int = 32): ByteArray { val random = SecureRandom() val bytes = ByteArray(length) return random.nextBytes(bytes) } ``` -------------------------------- ### Conversation per Event Flow Source: https://github.com/wireapp/integration-docs/blob/main/docs/001-webhook.mdx Outlines the process for creating a new Wire conversation for each significant external event, ensuring focused discussions and organized records. ```mermaid flowchart LR A[External event] --> B[Receive webhook] B --> C[Create conversation with relevant members] C --> D[Post initial messagewith event details] ``` -------------------------------- ### Webhook Notification Pipeline Flow Source: https://github.com/wireapp/integration-docs/blob/main/docs/001-webhook.mdx Illustrates the flow of a notification pipeline where an external event triggers a webhook, which is then processed to format and send a message to a Wire conversation. ```mermaid flowchart LR A[External event] --> B[Receive webhook] B --> C[Format message] C --> D[Send to Wire conversation] ``` -------------------------------- ### Create Channel Conversation Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/03-create-conversation.md Creates a channel conversation, similar to a group conversation but associated with a specific team. ```APIDOC ## createChannelConversationSuspending ### Description Creates a channel conversation with a specified name, list of user IDs, and a team ID. ### Method `createChannelConversationSuspending` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **name** (string) - Required - The name of the channel conversation. - **userIds** (List) - Required - A list of QualifiedIds for users to be included in the channel. - **teamId** (TeamId) - Required - The ID of the team to which the channel belongs. ### Request Example ```kotlin val createdChannelConversationId = applicationManager.createChannelConversationSuspending( name = "Channel Name", userIds = listOf( QualifiedId(userId1, userDomain1), QualifiedId(userId2, userDomain2) ), teamId = TeamId(value = UUID.fromString("my-team-id")) ) ``` ### Response #### Success Response (200) - **conversationId** (string) - The ID of the newly created channel conversation. #### Response Example (Not provided in source) ``` -------------------------------- ### Send Farewell Message on User Departure Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/01-events/16-on-user-left-conversation.mdx This Kotlin code snippet demonstrates how to send a farewell message when users leave a conversation. It retrieves user details and constructs a message to inform the conversation about the departure. ```kotlin import com.wire.integrations.sdk.WireMessage import com.wire.integrations.sdk.conversation.QualifiedId import com.wire.integrations.sdk.conversation.manager.ConversationManager // Assuming 'manager' is an instance of ConversationManager // Assuming 'manager.getUserSuspending' and 'manager.sendMessageSuspending' are available // This is a placeholder for the actual class or object where this function resides // For example, it could be part of an Integration class that extends a base class providing 'manager' // Example context: // class MyIntegration : BaseIntegration() { // override suspend fun onUserLeftConversation( // conversationId: QualifiedId, // members: List // ) { // // ... implementation below ... // } // } // Placeholder for the actual function implementation within a class context // The original snippet was missing the class context and imports, so they are added here for clarity. // In a real scenario, these would be provided by the SDK or your integration setup. // The actual function implementation as provided in the source: // override suspend fun onUserLeftConversation( // conversationId: QualifiedId, // members: List // ) { // val users = members.map { manager.getUserSuspending(it) } // val goodbyeText = buildString { // append("Bye ") // append(users.joinToString(" and ") { it.name }) // append("!") // } // val message = WireMessage.Text.create( // conversationId = conversationId, // text = goodbyeText // ) // manager.sendMessageSuspending(message) // } // To make this runnable as a standalone example, we need to mock or define dependencies. // However, the request is to provide the code EXACTLY as it appears in the source. // The source provided a snippet within a Tabs component, implying it's a method override. // Therefore, we will present the core logic as a method override. // Mocking necessary components for demonstration purposes if needed, but sticking to source code. // The provided snippet is a method override, so it should be presented as such. // Actual code from the source, presented as a method override: // Note: 'manager' is assumed to be available in the scope, likely as a member of the class. // The following code is the exact implementation provided in the source: // override suspend fun onUserLeftConversation( // conversationId: QualifiedId, // members: List // ) { // val users = members.map { manager.getUserSuspending(it) } // val goodbyeText = buildString { // append("Bye ") // append(users.joinToString(" and ") { it.name }) // append("!") // } // val message = WireMessage.Text.create( // conversationId = conversationId, // text = goodbyeText // ) // manager.sendMessageSuspending(message) // } // Since the request is to provide the code exactly as it appears, and the source uses a Tabs component // with a Kotlin code block, we will represent that block. The surrounding imports and class context // are implied by the `override` keyword and the use of `manager`. // The code block from the source: ```kotlin override suspend fun onUserLeftConversation( conversationId: QualifiedId, members: List ) { val users = members.map { manager.getUserSuspending(it) } val goodbyeText = buildString { append("Bye ") append(users.joinToString(" and ") { it.name }) append("!") } val message = WireMessage.Text.create( conversationId = conversationId, text = goodbyeText ) manager.sendMessageSuspending(message) } ``` ``` -------------------------------- ### Add members to a conversation (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/03-developer-interface/02-interactions/06-add-members-to-conversation.mdx Use `addMembersToConversation` to add members to a conversation. Ensure the conversation is a group or channel and the app has admin permissions. ```java WireApplicationManager applicationManager = wireAppSdk.getApplicationManager(); QualifiedId myConversationId = new QualifiedId( UUID.fromString("conversation-id"), "conversation-domain.com" ); List myListOfMembers = List.of( new QualifiedId( UUID.fromString("member-user-id"), "member-domain.com" ) ); applicationManager.addMembersToConversation( myConversationId, myListOfMembers ); ``` -------------------------------- ### Echoing a Received Text Message (Java) Source: https://github.com/wireapp/integration-docs/blob/main/docs/01-quickstart-advanced.mdx Responds to a received text message by creating a reply that includes the original message text and sender information. The `getManager()` method is used to send the reply. ```java @Override public void onTextMessageReceived(@NotNull WireMessage.Text wireMessage) { final WireMessage reply = WireMessage.Text.createReply( wireMessage.text() + " -- Sent from the SDK", wireMessage.mentions(), wireMessage.linkPreviews(), wireMessage, null); // The manager is accessible through the inherited WireEventsHandler class. // It is used to manage the Wire application's lifecycle and communication with the backend. getManager().sendMessage(reply); } ```