Skip to content

Commit

Permalink
feat: add invite users to channel method
Browse files Browse the repository at this point in the history
  • Loading branch information
markfarkas-camunda committed Dec 7, 2022
1 parent 3cd738e commit 83d913c
Show file tree
Hide file tree
Showing 13 changed files with 559 additions and 87 deletions.
46 changes: 46 additions & 0 deletions connectors/slack/element-templates/slack-connector.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
"id": "channel",
"label": "Channel"
},
{
"id": "invite",
"label": "Invite"
},
{
"id": "output",
"label": "Output Mapping"
Expand Down Expand Up @@ -65,6 +69,10 @@
{
"name": "Create Channel",
"value": "conversations.create"
},
{
"name": "Invite to Channel",
"value": "conversations.invite"
}
],
"binding": {
Expand Down Expand Up @@ -169,6 +177,44 @@
"equals": "chat.postMessage"
}
},
{
"label": "Channel Name",
"group": "invite",
"type": "String",
"feel": "optional",
"binding": {
"type": "zeebe:input",
"name": "data.channelName"
},
"constraints": {
"notEmpty": true,
"pattern": {
"value": "^(=|[-_a-z0-9]{1,80}$)",
"message": "May contain up to 80 lowercase letters, digits, underscores, and dashes"
}
},
"condition": {
"property": "method",
"equals": "conversations.invite"
}
},
{
"label": "Users",
"description": "Comma separated list of invitee names",
"group": "invite",
"type": "String",
"binding": {
"type": "zeebe:input",
"name": "data.users"
},
"constraints": {
"notEmpty": true
},
"condition": {
"property": "method",
"equals": "conversations.invite"
}
},
{
"label": "Result Variable",
"description": "Name of variable to store the response in",
Expand Down
5 changes: 5 additions & 0 deletions connectors/slack/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ except in compliance with the proprietary license.</license.inlineheader>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.camunda</groupId>
<artifactId>spring-zeebe-connector-runtime</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
import com.slack.api.methods.MethodsClient;
import com.slack.api.methods.SlackApiException;
import com.slack.api.methods.request.chat.ChatPostMessageRequest;
import com.slack.api.methods.request.users.UsersListRequest;
import com.slack.api.methods.request.users.UsersLookupByEmailRequest;
import com.slack.api.methods.response.chat.ChatPostMessageResponse;
import com.slack.api.methods.response.users.UsersListResponse;
import com.slack.api.methods.response.users.UsersLookupByEmailResponse;
import com.slack.api.model.User;
import io.camunda.connector.api.annotation.Secret;
Expand All @@ -24,16 +22,14 @@

public class ChatPostMessageData implements SlackRequestData {

private static final String EMAIL_REGEX = "^.+[@].+[.].{2,4}$";

@NotBlank @Secret private String channel;
@NotBlank @Secret private String text;

@Override
public SlackResponse invoke(MethodsClient methodsClient) throws SlackApiException, IOException {
if (channel.startsWith("@")) {
channel = getUserId(channel.substring(1), methodsClient);
} else if (isEmail(channel)) {
channel = DataLookupService.getUserIdByName(channel.substring(1), methodsClient);
} else if (DataLookupService.isEmail(channel)) {
channel = getUserIdByEmail(methodsClient);
}
ChatPostMessageRequest request =
Expand All @@ -52,44 +48,6 @@ public SlackResponse invoke(MethodsClient methodsClient) throws SlackApiExceptio
}
}

private String getUserId(String userName, MethodsClient methodsClient) {
String userId = null;
String nextCursor = null;

do {
UsersListRequest request = UsersListRequest.builder().limit(100).cursor(nextCursor).build();

try {
UsersListResponse response = methodsClient.usersList(request);
if (response.isOk()) {
userId =
response.getMembers().stream()
.filter(user -> userName.equals(user.getRealName()))
.map(User::getId)
.findFirst()
.orElse(null);
nextCursor = response.getResponseMetadata().getNextCursor();
} else {
throw new RuntimeException(
"Unable to find user with name: " + userName + "; message: " + response.getError());
}
} catch (Exception e) {
throw new RuntimeException("Unable to find user with name: " + userName, e);
}

} while (userId == null && nextCursor != null && !nextCursor.isBlank());

if (userId == null) {
throw new RuntimeException("Unable to find user with name: " + userName);
}

return userId;
}

private boolean isEmail(final String str) {
return str.matches(EMAIL_REGEX);
}

private String getUserIdByEmail(final MethodsClient methodsClient)
throws IOException, SlackApiException {
UsersLookupByEmailRequest lookupByEmailRequest =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.camunda.connector.slack;

import java.util.Objects;

public class Conversation {

private final String id;
private final String name;

public Conversation(com.slack.api.model.Conversation conversation) {
this.id = conversation.getId();
this.name = conversation.getName();
}

public String getId() {
return id;
}

public String getName() {
return name;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Conversation that = (Conversation) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name);
}

@Override
public int hashCode() {
return Objects.hash(id, name);
}

@Override
public String toString() {
return "Conversation{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,45 +42,4 @@ public int hashCode() {
public String toString() {
return "ConversationsCreateSlackResponse{" + "channel=" + channel + '}';
}

protected static class Conversation {

private final String id;
private final String name;

public Conversation(com.slack.api.model.Conversation conversation) {
this.id = conversation.getId();
this.name = conversation.getName();
}

public String getId() {
return id;
}

public String getName() {
return name;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Conversation that = (Conversation) o;
return Objects.equals(id, that.id) && Objects.equals(name, that.name);
}

@Override
public int hashCode() {
return Objects.hash(id, name);
}

@Override
public String toString() {
return "Conversation{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.camunda.connector.slack;

import com.slack.api.methods.MethodsClient;
import com.slack.api.methods.SlackApiException;
import com.slack.api.methods.request.conversations.ConversationsInviteRequest;
import com.slack.api.methods.response.conversations.ConversationsInviteResponse;
import io.camunda.connector.api.annotation.Secret;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

public class ConversationsInviteData implements SlackRequestData {

@NotBlank
@Secret
private String channelName;
@NotBlank
@Secret
private String users;

@Override
public SlackResponse invoke(MethodsClient methodsClient) throws SlackApiException, IOException {
List<String> userList = DataLookupService.getUserIdsFromNameOrEmail(DataLookupService.convertStringToList(users), methodsClient);
ConversationsInviteRequest request =
ConversationsInviteRequest.builder()
.channel(DataLookupService.getChannelIdByName(channelName, methodsClient))
.users(userList)
.build();

ConversationsInviteResponse response = methodsClient.conversationsInvite(request);

if (response.isOk()) {
return new ConversationsInviteSlackResponse(response);
} else {
throw new RuntimeException(response.getError());
}
}

public String getChannelName() {
return channelName;
}

public void setChannelName(String channelName) {
this.channelName = channelName;
}

public String getUsers() {
return users;
}

public void setUsers(String users) {
this.users = users;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConversationsInviteData that = (ConversationsInviteData) o;
return channelName.equals(that.channelName) && Objects.equals(users, that.users);
}

@Override
public int hashCode() {
return Objects.hash(channelName, users);
}

@Override
public String toString() {
return "ConversationsInviteData{" +
"channelName='" + channelName + '\'' +
", users=" + users +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.camunda.connector.slack;

import com.slack.api.methods.response.conversations.ConversationsInviteResponse;
import java.util.Objects;

public class ConversationsInviteSlackResponse implements SlackResponse {

private final Conversation channel;
private final String needed;
private final String provided;

public ConversationsInviteSlackResponse(ConversationsInviteResponse conversationsInviteResponse) {
this.channel = new Conversation(conversationsInviteResponse.getChannel());
this.needed = conversationsInviteResponse.getNeeded();
this.provided = conversationsInviteResponse.getProvided();
}

public Conversation getChannel() {
return channel;
}

public String getNeeded() {
return needed;
}

public String getProvided() {
return provided;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConversationsInviteSlackResponse that = (ConversationsInviteSlackResponse) o;
return Objects.equals(channel, that.channel) && Objects.equals(needed, that.needed) && Objects.equals(provided, that.provided);
}

@Override
public int hashCode() {
return Objects.hash(channel, needed, provided);
}
}
Loading

0 comments on commit 83d913c

Please sign in to comment.