Skip to content

Commit 2fa9842

Browse files
committed
Adding Attachment support
fixing the way we were sending payloads to the server. It broke with attachments.
1 parent 64cf20a commit 2fa9842

6 files changed

Lines changed: 213 additions & 24 deletions

File tree

src/main/java/in/ashwanthkumar/slack/webhook/Slack.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package in.ashwanthkumar.slack.webhook;
22

33
import in.ashwanthkumar.slack.webhook.service.SlackService;
4+
import in.ashwanthkumar.slack.webhook.util.Lists;
45

56
import java.io.IOException;
7+
import java.util.List;
68

79
import static in.ashwanthkumar.slack.webhook.util.StringUtils.isEmpty;
810

@@ -84,4 +86,26 @@ public void push(SlackMessage message) throws IOException {
8486
slackService.push(webhookUrl, message, user, icon, channel);
8587
}
8688
}
89+
90+
/**
91+
* Publish message as SlackAttachment
92+
*
93+
* @param attachment SlackAttachment to send
94+
* @throws IOException
95+
*/
96+
public void push(SlackAttachment attachment) throws IOException {
97+
if (attachment != null) {
98+
slackService.push(webhookUrl, new SlackMessage(), user, icon, channel, Lists.of(attachment));
99+
}
100+
}
101+
102+
/**
103+
* Publish message as SlackAttachment
104+
*
105+
* @param attachments SlackAttachment to send
106+
* @throws IOException
107+
*/
108+
public void push(List<SlackAttachment> attachments) throws IOException {
109+
slackService.push(webhookUrl, new SlackMessage(), user, icon, channel, attachments);
110+
}
87111
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package in.ashwanthkumar.slack.webhook;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
8+
/**
9+
* Ref - https://api.slack.com/docs/attachments
10+
*/
11+
public class SlackAttachment {
12+
@SerializedName("fallback")
13+
private String fallback;
14+
@SerializedName("color")
15+
private String color;
16+
@SerializedName("pretext")
17+
private String pretext;
18+
@SerializedName("author_name")
19+
private String authorName;
20+
@SerializedName("author_link")
21+
private String authorLink;
22+
@SerializedName("author_icon")
23+
private String authorIcon;
24+
@SerializedName("title")
25+
private String title;
26+
@SerializedName("title_link")
27+
private String titleLink;
28+
@SerializedName("text")
29+
private String text;
30+
@SerializedName("fields")
31+
private List<Field> fields = new ArrayList<Field>();
32+
33+
public SlackAttachment(String text) {
34+
text(text);
35+
}
36+
37+
public static class Field {
38+
@SerializedName("title")
39+
private String title;
40+
@SerializedName("value")
41+
private String value;
42+
@SerializedName("short")
43+
private boolean isShort;
44+
45+
public Field(String title, String value, boolean isShort) {
46+
this.title = title;
47+
this.value = value;
48+
this.isShort = isShort;
49+
}
50+
51+
public String getTitle() {
52+
return title;
53+
}
54+
55+
public String getValue() {
56+
return value;
57+
}
58+
59+
public boolean isShort() {
60+
return isShort;
61+
}
62+
}
63+
64+
public SlackAttachment fallback(String fallbackText) {
65+
this.fallback = fallbackText;
66+
return this;
67+
}
68+
69+
public SlackAttachment color(String colorInHex) {
70+
this.color = colorInHex;
71+
return this;
72+
}
73+
74+
public SlackAttachment preText(String pretext) {
75+
this.pretext = pretext;
76+
return this;
77+
}
78+
79+
public SlackAttachment author(String name) {
80+
this.authorName = name;
81+
return this;
82+
}
83+
84+
public SlackAttachment author(String name, String link) {
85+
this.authorLink = link;
86+
return author(name);
87+
}
88+
89+
public SlackAttachment author(String name, String link, String iconOrImageLink) {
90+
this.authorIcon = iconOrImageLink;
91+
return author(name, link);
92+
}
93+
94+
public SlackAttachment title(String title) {
95+
this.title = title;
96+
return this;
97+
}
98+
99+
public SlackAttachment title(String title, String link) {
100+
this.titleLink = link;
101+
return title(title);
102+
}
103+
104+
public SlackAttachment text(String text) {
105+
this.text = text;
106+
return this;
107+
}
108+
109+
public SlackAttachment text(SlackMessage message) {
110+
return text(message.toString());
111+
}
112+
113+
public SlackAttachment addField(Field field) {
114+
this.fields.add(field);
115+
return this;
116+
}
117+
118+
public String getText() {
119+
return text;
120+
}
121+
}

src/main/java/in/ashwanthkumar/slack/webhook/SlackMessage.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
/**
77
* Wrapper to build rich text content in Slack
8+
* Ref - https://api.slack.com/docs/formatting
89
*/
910
public class SlackMessage {
1011
private StringBuilder textBuffer = new StringBuilder();
@@ -57,11 +58,21 @@ public SlackMessage preformatted(String text) {
5758
}
5859

5960
public SlackMessage quote(String text) {
60-
textBuffer.append("> ").append(text).append("\n");
61+
textBuffer.append("\n> ").append(text).append("\n");
6162
return this;
6263
}
6364

6465
public String toString() {
6566
return textBuffer.toString();
6667
}
68+
69+
public String rawText() {
70+
// We're not removing link because it's readable the way it is.
71+
return textBuffer.toString()
72+
.replaceAll("(.*)\\*(.*)\\*(.*)", "$1$2$3") // Remove bold formatting
73+
.replaceAll("(.*)_(.*)_(.*)", "$1$2$3") // Remove italic formatting
74+
.replaceAll("(.*)```(.*)```(.*)", "$1$2$3") // Remove pretext formatting
75+
.replaceAll("(.*)`(.*)`(.*)", "$1$2$3") // Remove code formatting
76+
.replaceAll("\n>\\s+(.*)\n", "$1"); // Remove Quote formatting
77+
}
6778
}
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
package in.ashwanthkumar.slack.webhook.service;
22

33
import com.google.api.client.http.GenericUrl;
4-
import com.google.api.client.http.HttpRequest;
54
import com.google.api.client.http.HttpRequestFactory;
65
import com.google.api.client.http.HttpTransport;
6+
import com.google.api.client.http.UrlEncodedContent;
77
import com.google.api.client.http.javanet.NetHttpTransport;
8-
import com.google.api.client.http.json.JsonHttpContent;
9-
import com.google.api.client.json.gson.GsonFactory;
8+
import com.google.api.client.util.Maps;
9+
import com.google.gson.Gson;
10+
import in.ashwanthkumar.slack.webhook.SlackAttachment;
1011
import in.ashwanthkumar.slack.webhook.SlackMessage;
1112

1213
import java.io.IOException;
14+
import java.util.ArrayList;
1315
import java.util.HashMap;
16+
import java.util.List;
1417
import java.util.Map;
1518

1619
import static in.ashwanthkumar.slack.webhook.util.StringUtils.isNotEmpty;
@@ -20,8 +23,8 @@ public class SlackService {
2023
private final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
2124
private final HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory();
2225

23-
public void push(String webHookUrl, SlackMessage text, String username, String imageOrIcon, String destination) throws IOException {
24-
Map<String, String> payload = new HashMap<String, String>();
26+
public void push(String webHookUrl, SlackMessage text, String username, String imageOrIcon, String destination, List<SlackAttachment> attachments) throws IOException {
27+
Map<String, Object> payload = new HashMap<String, Object>();
2528
if (isNotEmpty(username)) {
2629
payload.put("username", username);
2730
}
@@ -33,12 +36,23 @@ public void push(String webHookUrl, SlackMessage text, String username, String i
3336
if (isNotEmpty(destination)) {
3437
payload.put("channel", destination);
3538
}
39+
if (!attachments.isEmpty()) {
40+
payload.put("attachments", attachments);
41+
}
3642
payload.put("text", text.toString());
3743
execute(webHookUrl, payload);
3844
}
3945

40-
public void execute(String webHookUrl, Map<String, String> payload) throws IOException {
41-
HttpRequest httpRequest = requestFactory.buildPostRequest(new GenericUrl(webHookUrl), new JsonHttpContent(new GsonFactory(), payload));
42-
httpRequest.execute();
46+
public void push(String webHookUrl, SlackMessage text, String username, String imageOrIcon, String destination) throws IOException {
47+
push(webHookUrl, text, username, imageOrIcon, destination, new ArrayList<SlackAttachment>());
48+
}
49+
50+
public void execute(String webHookUrl, Map<String, Object> payload) throws IOException {
51+
String jsonEncodedMessage = new Gson().toJson(payload);
52+
HashMap<Object, Object> payloadToSend = Maps.newHashMap();
53+
payloadToSend.put("payload", jsonEncodedMessage);
54+
55+
requestFactory.buildPostRequest(new GenericUrl(webHookUrl), new UrlEncodedContent(payloadToSend))
56+
.execute();
4357
}
4458
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package in.ashwanthkumar.slack.webhook.util;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
public class Lists {
8+
public static <T> List<T> of(T... elements) {
9+
if(elements == null) return new ArrayList<T>();
10+
else return Arrays.asList(elements);
11+
}
12+
}

src/test/java/in/ashwanthkumar/slack/webhook/SlackMessageTest.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import org.junit.Test;
44

55
import static org.hamcrest.CoreMatchers.is;
6-
import static org.junit.Assert.*;
6+
import static org.junit.Assert.assertThat;
77

88
public class SlackMessageTest {
99

@@ -15,44 +15,51 @@ public void shouldAddNormalText() {
1515

1616
@Test
1717
public void shouldAddBoldText() {
18-
String boldText = new SlackMessage().text("This text is in ").bold("BOLD").text(", but still lets see").toString();
19-
assertThat(boldText, is("This text is in *BOLD*, but still lets see"));
18+
SlackMessage message = new SlackMessage().text("This text is in ").bold("BOLD").text(", but still lets see");
19+
assertThat(message.toString(), is("This text is in *BOLD*, but still lets see"));
20+
assertThat(message.rawText(), is("This text is in BOLD, but still lets see"));
2021
}
2122

2223
@Test
2324
public void shouldAddItalicText() {
24-
String italicText = new SlackMessage().text("Some text can be ").italic("Italic").text(". :)").toString();
25-
assertThat(italicText, is("Some text can be _Italic_. :)"));
25+
SlackMessage message = new SlackMessage().text("Some text can be ").italic("Italic").text(". :)");
26+
assertThat(message.toString(), is("Some text can be _Italic_. :)"));
27+
assertThat(message.rawText(), is("Some text can be Italic. :)"));
2628
}
2729

2830
@Test
2931
public void shouldAddCodeText() {
30-
String codeText = new SlackMessage().text("class ").code("SlackText").text(" {}").toString();
31-
assertThat(codeText, is("class `SlackText` {}"));
32+
SlackMessage message = new SlackMessage().text("class ").code("SlackText").text(" {}");
33+
assertThat(message.toString(), is("class `SlackText` {}"));
34+
assertThat(message.rawText(), is("class SlackText {}"));
3235
}
3336

3437
@Test
3538
public void shouldAddPreformattedText() {
36-
String preformatted = new SlackMessage().preformatted("random preformatted text").toString();
37-
assertThat(preformatted, is("```random preformatted text```"));
39+
SlackMessage message = new SlackMessage().preformatted("random preformatted text");
40+
assertThat(message.toString(), is("```random preformatted text```"));
41+
assertThat(message.rawText(), is("random preformatted text"));
3842
}
3943

4044
@Test
4145
public void shouldAddQuoteText() {
42-
String quoteText = new SlackMessage().quote("Krishna says ...").toString();
43-
assertThat(quoteText, is("> Krishna says ...\n"));
46+
SlackMessage message = new SlackMessage().quote("Krishna says ...");
47+
assertThat(message.toString(), is("\n> Krishna says ...\n"));
48+
assertThat(message.rawText(), is("Krishna says ..."));
4449
}
4550

4651
@Test
4752
public void shouldAddJustLink() {
48-
String linkText = new SlackMessage().link("http://ashwanthkumar.in").toString();
49-
assertThat(linkText, is("<http://ashwanthkumar.in>"));
53+
SlackMessage message = new SlackMessage().link("http://ashwanthkumar.in");
54+
assertThat(message.toString(), is("<http://ashwanthkumar.in>"));
55+
assertThat(message.rawText(), is("<http://ashwanthkumar.in>"));
5056
}
5157

5258
@Test
5359
public void shouldAddLinkWithText() {
54-
String linkText = new SlackMessage().link("http://ashwanthkumar.in", "Ashwanth Kumar").toString();
55-
assertThat(linkText, is("<http://ashwanthkumar.in|Ashwanth Kumar>"));
60+
SlackMessage message = new SlackMessage().link("http://ashwanthkumar.in", "Ashwanth Kumar");
61+
assertThat(message.toString(), is("<http://ashwanthkumar.in|Ashwanth Kumar>"));
62+
assertThat(message.rawText(), is("<http://ashwanthkumar.in|Ashwanth Kumar>"));
5663
}
5764

5865

0 commit comments

Comments
 (0)