Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
Merge pull request #22 from palantir/develop
Browse files Browse the repository at this point in the history
1.0.0-rc
  • Loading branch information
elektron9 authored Jul 13, 2017
2 parents d5aab07 + 3ea8c15 commit 59d2c8a
Show file tree
Hide file tree
Showing 41 changed files with 870 additions and 277 deletions.
26 changes: 26 additions & 0 deletions extras/jackson-support/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/junit.gradle"

dependencies {
compile "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
compile "com.fasterxml.jackson.module:jackson-module-afterburner:${jacksonVersion}"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jacksonVersion}"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}"
compile "com.fasterxml.jackson.datatype:jackson-datatype-guava:${jacksonVersion}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.palantir.roboslack.api.testing;
package com.palantir.roboslack.jackson;


import com.fasterxml.jackson.databind.DeserializationFeature;
Expand All @@ -25,11 +25,11 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;

final class ObjectMappers {
public final class ObjectMappers {

private ObjectMappers() {}

static ObjectMapper newObjectMapper() {
public static ObjectMapper newObjectMapper() {
return new ObjectMapper().registerModule(new GuavaModule())
.registerModule(new Jdk8Module().configureAbsentsAsNulls(true))
.registerModule(new AfterburnerModule())
Expand Down
25 changes: 25 additions & 0 deletions extras/slack-clients/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

apply from: "${rootDir}/gradle/java.gradle"
apply from: "${rootDir}/gradle/junit.gradle"

dependencies {
compile project(":extras:jackson-support")
compile "com.google.guava:guava:${guavaVersion}"
compile "com.squareup.retrofit2:retrofit:${retrofitVersion}"
compile "com.squareup.retrofit2:converter-jackson:${retrofitVersion}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.palantir.roboslack.clients;

import com.palantir.roboslack.jackson.ObjectMappers;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.converter.jackson.JacksonConverterFactory;

/**
* Utility class for generating service clients for RPC calls to Slack (intended for internal use only).
*
* @since 1.0.0
*/
public final class SlackClients {

private static final String DEFAULT_USER_AGENT = "RoboSlack/1.0.0";

private SlackClients() {}

private static String addTrailingSlash(String uri) {
return uri.charAt(uri.length() - 1) == '/' ? uri : uri + "/";
}

private static OkHttpClient createOkHttpClient(String userAgent) {
return new OkHttpClient.Builder()
.addInterceptor(UserAgentInterceptor.of(userAgent))
.connectionPool(new ConnectionPool(100, 10, TimeUnit.MINUTES))
.build();
}

public static <T> T create(Class<T> clazz, String userAgent, String uri,
Converter.Factory... specialPurposeConverters) {
Retrofit.Builder retrofit = new Retrofit.Builder()
.baseUrl(addTrailingSlash(uri))
.client(createOkHttpClient(userAgent));
Stream.of(specialPurposeConverters).forEach(retrofit::addConverterFactory);
retrofit.addConverterFactory(JacksonConverterFactory.create(ObjectMappers.newObjectMapper()));
return retrofit.build().create(clazz);
}

public static <T> T create(Class<T> clazz, String uri, Converter.Factory... specialPurposeConverters) {
return create(clazz, DEFAULT_USER_AGENT, uri, specialPurposeConverters);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.palantir.roboslack.clients;

import static com.google.common.base.Preconditions.checkArgument;

import java.io.IOException;
import java.util.regex.Pattern;
import okhttp3.Interceptor;
import okhttp3.Response;

/**
* Intercepts requests, then injects and validates the user agent string.
*
* @since 1.0.0
*/
public final class UserAgentInterceptor implements Interceptor {

private static final Pattern VALID_USER_AGENT = Pattern.compile("[A-Za-z0-9()\\-#;/.,_\\s]+");
private final String userAgent;

private UserAgentInterceptor(String userAgent) {
checkArgument(VALID_USER_AGENT.matcher(userAgent).matches(),
"User Agent must match pattern '%s': %s", VALID_USER_AGENT, userAgent);
this.userAgent = userAgent;
}

public static UserAgentInterceptor of(String userAgent) {
return new UserAgentInterceptor(userAgent);
}

@Override
public Response intercept(Chain chain) throws IOException {
return chain.proceed(chain.request().newBuilder()
.header("User-Agent", userAgent)
.build());
}

}
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Project Dependencies
guavaVersion = 22.0
httpRemotingVersion = 2.5.1
retrofitVersion = 2.3.0
immutablesVersion = 2.5.3
jacksonVersion = 2.8.8
jaxRsVersion = 2.0.1
mockitoVersion = 1.10.19
retrofitVersion = 2.3.0

# Build System
baselineVersion = 0.14.0
Expand All @@ -16,6 +15,7 @@ nebulaPublishingPluginVersion = 5.1.0
bintrayPluginVersion = 1.7.3

# Testing
awaitilityVersion = 3.0.0
hamcrestVersion = 1.3
junitPlatformVersion = 1.0.0-M4
junitJupiterVersion = 5.0.0-M4
junitPlatformVersion = 1.0.0-M5
junitJupiterVersion = 5.0.0-M5
6 changes: 1 addition & 5 deletions roboslack-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@ apply from: "${rootDir}/gradle/immutables.gradle"
apply from: "${rootDir}/gradle/publish.gradle"

dependencies {
compile project(":extras:jackson-support")
compile "com.google.guava:guava:${guavaVersion}"
compile "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
compile "com.fasterxml.jackson.module:jackson-module-afterburner:${jacksonVersion}"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jacksonVersion}"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}"
compile "com.fasterxml.jackson.datatype:jackson-datatype-guava:${jacksonVersion}"

testCompile "org.hamcrest:hamcrest-all:${hamcrestVersion}"
testCompile "org.mockito:mockito-core:${mockitoVersion}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ public interface Builder {
Builder iconUrl(URL iconUrl);
Builder username(String username);
Builder channel(String channel);
Builder from(MessageRequest messageRequest);
MessageRequest build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.palantir.roboslack.api.attachments.components.Author;
import com.palantir.roboslack.api.attachments.components.Color;
import com.palantir.roboslack.api.attachments.components.Field;
import com.palantir.roboslack.api.attachments.components.Footer;
import com.palantir.roboslack.api.attachments.components.Title;
import com.palantir.roboslack.api.markdown.MarkdownInput;
import com.palantir.roboslack.utils.MorePreconditions;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import org.immutables.value.Value;

Expand All @@ -54,6 +58,7 @@ public abstract class Attachment {
private static final String PRETEXT_FIELD = "pretext";
private static final String IMAGE_URL_FIELD = "image_url";
private static final String THUMB_URL_FIELD = "thumb_url";
private static final String MARKDOWN_INPUTS_FIELD = "mrkdwn_in";

/**
* Generate a new {@link Attachment.Builder}.
Expand All @@ -67,13 +72,11 @@ public static Builder builder() {
@Value.Check
protected final void check() {
checkArgument(!Strings.isNullOrEmpty(fallback()), "Attachment fallback message cannot be null or empty");
MorePreconditions.checkDoesNotContainMarkdown(FALLBACK_FIELD, fallback());
pretext().ifPresent(s -> MorePreconditions.checkDoesNotContainMarkdown(PRETEXT_FIELD, s));
}

/**
* The {@link List} get {@link Field}s for this {@link Attachment}. Fields are displayed in a tabular fashion near
* the bottom get the {@link Attachment}.
* the bottom of the {@link Attachment}.
*
* @return the {@link List} get {@link Field}s
*/
Expand All @@ -82,25 +85,10 @@ public List<Field> fields() {
return ImmutableList.of();
}

public interface Builder {
Builder fallback(String fallback);
Builder color(Color color);
Builder pretext(String pretext);
Builder author(Author author);
Builder title(Title title);
Builder text(String text);
Builder addFields(Field field);
Builder addFields(Field... fields);
Builder fields(Iterable<? extends Field> elements);
Builder imageUrl(URL imageUrl);
Builder thumbUrl(URL thumbUrl);
Builder footer(Footer footer);
Attachment build();
}

/**
* The plaintext summary of this {@link Attachment}. This text is used in clients that don't show formatted text
* (eg. IRC, mobile notifications) and should not contain any markup.
* The plaintext summary of this {@link Attachment} used in clients that don't display formatted text. <br/>
* <b>Note:</b> If this text contains any {@link com.palantir.roboslack.api.markdown.SlackMarkdown} special
* characters, they will be treated as literal plaintext characters when rendered in any Slack client.
*
* @return the {@code fallback} text
*/
Expand Down Expand Up @@ -201,4 +189,60 @@ public Footer footer() {
return null;
}

/**
* A special list of flags that tells Slack where to expect Markdown in an Attachment.
* Valid values are ["pretext", "text", "fields"].
*
* @return the {@link Collection} of {@code markdownInputs}
*/
@Value.Default
@JsonProperty(MARKDOWN_INPUTS_FIELD)
public Set<MarkdownInput> markdownInputs() {
// inspect the values of the Attachment object and create the mrkdwnIn list.
ImmutableSet.Builder<MarkdownInput> markdownInputs = ImmutableSet.builder();
// check if the pretext contains Markdown.
if (pretext().isPresent() && MorePreconditions.containsMarkdown(pretext().get())) {
markdownInputs.add(MarkdownInput.PRETEXT);
}
// check if the text contains Markdown.
if (text().isPresent() && MorePreconditions.containsMarkdown(text().get())) {
markdownInputs.add(MarkdownInput.TEXT);
}
// check if any of the Fields' values contain Markdown.
fields().stream()
.map(Field::value)
.filter(MorePreconditions::containsMarkdown)
.findFirst()
.ifPresent(ignored -> markdownInputs.add(MarkdownInput.FIELDS));
return markdownInputs.build();
}

public interface Builder {
Builder fallback(String fallback);

Builder color(Color color);

Builder pretext(String pretext);

Builder author(Author author);

Builder title(Title title);

Builder text(String text);

Builder addFields(Field field);

Builder addFields(Field... fields);

Builder fields(Iterable<? extends Field> elements);

Builder imageUrl(URL imageUrl);

Builder thumbUrl(URL thumbUrl);

Builder footer(Footer footer);

Attachment build();
}

}
Loading

0 comments on commit 59d2c8a

Please sign in to comment.