diff --git a/README.md b/README.md index 793ab685..bd4c251f 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,17 @@ slackResponse.addReaction("thumbsup") ![image][img-emoji-reaction] +You can remove an emoji reaction to a previously-sent message like this: + +Example: + +```groovy +def slackResponse = slackSend(channel: "emoji-demo", message: "Here is the primary message") +slackResponse.addReaction("thumbsup") +// ... do some stuff +slackResponse.removeReaction("thumbsup") +``` + This may only work reliably in channels (as opposed to private messages) due to [limitations in the Slack API](https://api.slack.com/methods/chat.postMessage) (See "Post to an IM channel"). This does not currently work in a situation where Jenkins is restarted between sending the initial message and adding the reaction. If this is something you need, please file an issue. diff --git a/src/main/java/jenkins/plugins/slack/SlackService.java b/src/main/java/jenkins/plugins/slack/SlackService.java index 23ad91c0..a23186ee 100755 --- a/src/main/java/jenkins/plugins/slack/SlackService.java +++ b/src/main/java/jenkins/plugins/slack/SlackService.java @@ -21,5 +21,15 @@ public interface SlackService { boolean addReaction(String channelId, String timestamp, String emojiName); + /** + * Remove an emoji reaction to a message. + * @param channelId - Slack's internal channel id (i.e. what's returned in a `chat.postMessage` response) + * @param timestamp - Timestamp identifying the message + * @param emojiName - The name of the emoji to add in reaction to the message (no colons) + * + * @return boolean indicating whether the API request succeeded + */ + boolean removeReaction(String channelId, String timestamp, String emojiName); + String getResponseString(); } diff --git a/src/main/java/jenkins/plugins/slack/StandardSlackService.java b/src/main/java/jenkins/plugins/slack/StandardSlackService.java index 49965620..f5229ad8 100755 --- a/src/main/java/jenkins/plugins/slack/StandardSlackService.java +++ b/src/main/java/jenkins/plugins/slack/StandardSlackService.java @@ -427,6 +427,22 @@ public boolean addReaction(String channelId, String timestamp, String emojiName) return postToSlack("reactions.add", json); } + /** + * Remove an emoji reaction from a message. + */ + @Override + public boolean removeReaction(String channelId, String timestamp, String emojiName) { + JSONObject json = SlackReactionRequest.builder() + .withChannelId(channelId) + .withTimestamp(timestamp) + .withEmojiName(emojiName) + .build() + .getBody(); + + logger.fine("Removing reaction: " + json.toString()); + return postToSlack("reactions.remove", json); + } + private String getTokenToUse(String authTokenCredentialId, String token) { if (!StringUtils.isEmpty(authTokenCredentialId)) { StringCredentials credentials = CredentialsObtainer.lookupCredentials(authTokenCredentialId); diff --git a/src/main/java/jenkins/plugins/slack/workflow/SlackResponse.java b/src/main/java/jenkins/plugins/slack/workflow/SlackResponse.java index 4eba766f..67e7f46d 100644 --- a/src/main/java/jenkins/plugins/slack/workflow/SlackResponse.java +++ b/src/main/java/jenkins/plugins/slack/workflow/SlackResponse.java @@ -65,4 +65,20 @@ public boolean addReaction(String emojiName) { return slackService.addReaction(channelId, ts, emojiName); } + + /** + * Remove an emoji reaction to the message that this `SlackResponse` points to. + * + * @param emojiName - name of the emoji (no colons), e.g. `thumbsup` + * + * @return boolean indicating whether the API request succeeded + */ + @Whitelisted + public boolean removeReaction(String emojiName) { + if (slackService == null) { + return false; + } + + return slackService.removeReaction(channelId, ts, emojiName); + } } diff --git a/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java b/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java index fcd90982..c4e07447 100644 --- a/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java +++ b/src/test/java/jenkins/plugins/slack/SlackNotifierTest.java @@ -94,6 +94,11 @@ public boolean addReaction(String channelId, String timestamp, String emojiName) return response; } + @Override + public boolean removeReaction(String channelId, String timestamp, String emojiName) { + return response; + } + public void setResponse(boolean response) { this.response = response; } diff --git a/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java b/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java index bce93425..9ada3f56 100755 --- a/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java +++ b/src/test/java/jenkins/plugins/slack/StandardSlackServiceTest.java @@ -302,4 +302,20 @@ public void usernameAndNotBotUserReturnsTrue() { assertTrue(service.publish("message")); } + @Test + public void shouldRemoveAReaction() { + StandardSlackServiceStub service = new StandardSlackServiceStub( + StandardSlackService.builder() + .withBaseUrl("") + .withTeamDomain("domain") + .withBotUser(true) + .withRoomId("#room1") + .withPopulatedToken("token") + .withUsername("username")); + CloseableHttpClientStub httpClientStub = new CloseableHttpClientStub(); + httpClientStub.setHttpStatus(HttpStatus.SC_OK); + service.setHttpClient(httpClientStub); + assertTrue(service.removeReaction("#my-room", "12345", "thumbup")); + } + }