From 90e3cd0f7c58d5b49bb7e1a50120b23a8b3e86d2 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Fri, 16 Oct 2026 11:41:31 -0400 Subject: [PATCH] feat: add the user_connection_status_requested event model Slack sends this event when it has no connection status for a user, and apps answer with apps.user.connection.update. The model lets Bolt apps register app.event(UserConnectionStatusRequestedEvent.class, ...). --- .../UserConnectionStatusRequestedEvent.java | 18 ++++++++++ ...serConnectionStatusRequestedEventTest.java | 36 +++++++++++++++++++ .../UserConnectionStatusRequestedHandler.java | 13 +++++++ .../UserConnectionStatusRequestedPayload.java | 25 +++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 slack-api-model/src/main/java/com/slack/api/model/event/UserConnectionStatusRequestedEvent.java create mode 100644 slack-api-model/src/test/java/test_locally/api/model/event/UserConnectionStatusRequestedEventTest.java create mode 100644 slack-app-backend/src/main/java/com/slack/api/app_backend/events/handler/UserConnectionStatusRequestedHandler.java create mode 100644 slack-app-backend/src/main/java/com/slack/api/app_backend/events/payload/UserConnectionStatusRequestedPayload.java diff --git a/slack-api-model/src/main/java/com/slack/api/model/event/UserConnectionStatusRequestedEvent.java b/slack-api-model/src/main/java/com/slack/api/model/event/UserConnectionStatusRequestedEvent.java new file mode 100644 index 000000000..34c401136 --- /dev/null +++ b/slack-api-model/src/main/java/com/slack/api/model/event/UserConnectionStatusRequestedEvent.java @@ -0,0 +1,18 @@ +package com.slack.api.model.event; + +import lombok.Data; + +/** + * Slack sends the user_connection_status_requested event when it has no connection status for a user. + * Answer it with the apps.user.connection.update API method. + *

+ * https://docs.slack.dev/reference/events/user_connection_status_requested + */ +@Data +public class UserConnectionStatusRequestedEvent implements Event { + + public static final String TYPE_NAME = "user_connection_status_requested"; + + private final String type = TYPE_NAME; + private String user; +} diff --git a/slack-api-model/src/test/java/test_locally/api/model/event/UserConnectionStatusRequestedEventTest.java b/slack-api-model/src/test/java/test_locally/api/model/event/UserConnectionStatusRequestedEventTest.java new file mode 100644 index 000000000..3c487fe3c --- /dev/null +++ b/slack-api-model/src/test/java/test_locally/api/model/event/UserConnectionStatusRequestedEventTest.java @@ -0,0 +1,36 @@ +package test_locally.api.model.event; + +import com.google.gson.Gson; +import com.slack.api.model.event.UserConnectionStatusRequestedEvent; +import org.junit.Test; +import test_locally.unit.GsonFactory; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +public class UserConnectionStatusRequestedEventTest { + + @Test + public void typeName() { + assertThat(UserConnectionStatusRequestedEvent.TYPE_NAME, is("user_connection_status_requested")); + } + + @Test + public void deserialize() { + String json = "{\"type\":\"user_connection_status_requested\",\"user\":\"U123ABC456\"}"; + UserConnectionStatusRequestedEvent event = + GsonFactory.createSnakeCase().fromJson(json, UserConnectionStatusRequestedEvent.class); + assertThat(event.getType(), is("user_connection_status_requested")); + assertThat(event.getUser(), is("U123ABC456")); + } + + @Test + public void serialize() { + Gson gson = GsonFactory.createSnakeCase(); + UserConnectionStatusRequestedEvent event = new UserConnectionStatusRequestedEvent(); + event.setUser("U123ABC456"); + String generatedJson = gson.toJson(event); + String expectedJson = "{\"type\":\"user_connection_status_requested\",\"user\":\"U123ABC456\"}"; + assertThat(generatedJson, is(expectedJson)); + } +} diff --git a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/handler/UserConnectionStatusRequestedHandler.java b/slack-app-backend/src/main/java/com/slack/api/app_backend/events/handler/UserConnectionStatusRequestedHandler.java new file mode 100644 index 000000000..54792dbba --- /dev/null +++ b/slack-app-backend/src/main/java/com/slack/api/app_backend/events/handler/UserConnectionStatusRequestedHandler.java @@ -0,0 +1,13 @@ +package com.slack.api.app_backend.events.handler; + +import com.slack.api.app_backend.events.EventHandler; +import com.slack.api.app_backend.events.payload.UserConnectionStatusRequestedPayload; +import com.slack.api.model.event.UserConnectionStatusRequestedEvent; + +public abstract class UserConnectionStatusRequestedHandler extends EventHandler { + + @Override + public String getEventType() { + return UserConnectionStatusRequestedEvent.TYPE_NAME; + } +} diff --git a/slack-app-backend/src/main/java/com/slack/api/app_backend/events/payload/UserConnectionStatusRequestedPayload.java b/slack-app-backend/src/main/java/com/slack/api/app_backend/events/payload/UserConnectionStatusRequestedPayload.java new file mode 100644 index 000000000..ad3cd8cae --- /dev/null +++ b/slack-app-backend/src/main/java/com/slack/api/app_backend/events/payload/UserConnectionStatusRequestedPayload.java @@ -0,0 +1,25 @@ +package com.slack.api.app_backend.events.payload; + +import com.slack.api.model.event.UserConnectionStatusRequestedEvent; +import lombok.Data; + +import java.util.List; + +@Data +public class UserConnectionStatusRequestedPayload implements EventsApiPayload { + + private String token; + private String enterpriseId; + private String teamId; + private String apiAppId; + private String type; + private List authedUsers; + private List authedTeams; + private List authorizations; + private boolean isExtSharedChannel; + private String eventId; + private Integer eventTime; + private String eventContext; + + private UserConnectionStatusRequestedEvent event; +}