diff --git a/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/AbstractChatMessageParams.java b/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/AbstractChatMessageParams.java index 93672933..6d4bd588 100644 --- a/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/AbstractChatMessageParams.java +++ b/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/AbstractChatMessageParams.java @@ -6,8 +6,10 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.hubspot.slack.client.models.Metadata; import java.util.Optional; import org.immutables.value.Value.Check; +import org.immutables.value.Value.Default; @JsonNaming(SnakeCaseStrategy.class) public abstract class AbstractChatMessageParams implements MessageParams { @@ -34,10 +36,22 @@ public abstract class AbstractChatMessageParams implements MessageParams { public abstract Optional getUnfurlMedia(); + @JsonInclude(JsonInclude.Include.NON_EMPTY) public abstract Optional getReplyBroadcast(); + public abstract Optional getParse(); + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public abstract Optional getMetadata(); + + @Default + public Optional getMrkdwn() { + return Optional.of(true); + } + @Check public void check() { + MessageParams.super.check(); Preconditions.checkState( (getText().isPresent() && !Strings.isNullOrEmpty(getText().get())) || !getAttachments().isEmpty() || diff --git a/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/ChatScheduleMessageParamsIF.java b/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/ChatScheduleMessageParamsIF.java index dc1484d9..6bc6b14f 100644 --- a/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/ChatScheduleMessageParamsIF.java +++ b/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/ChatScheduleMessageParamsIF.java @@ -1,11 +1,13 @@ package com.hubspot.slack.client.methods.params.chat; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.hubspot.immutables.style.HubSpotStyle; +import com.hubspot.slack.client.models.Metadata; import java.util.Optional; import org.immutables.value.Value.Check; import org.immutables.value.Value.Default; @@ -42,8 +44,16 @@ default String getThreadTs() { Optional getUnfurlMedia(); + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("reply_broadcast") + Optional getReplyAsBroadcast(); + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + Optional getMetadata(); + @Check default void check() { + MessageParams.super.check(); Preconditions.checkState( (getText().isPresent() && !Strings.isNullOrEmpty(getText().get())) || !getAttachments().isEmpty() || diff --git a/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/MessageParams.java b/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/MessageParams.java index bda4728c..d5cacfc2 100644 --- a/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/MessageParams.java +++ b/slack-base/src/main/java/com/hubspot/slack/client/methods/params/chat/MessageParams.java @@ -1,12 +1,16 @@ package com.hubspot.slack.client.methods.params.chat; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.google.common.base.Preconditions; import com.hubspot.slack.client.methods.interceptor.HasChannel; import com.hubspot.slack.client.models.Attachment; import com.hubspot.slack.client.models.blocks.Block; +import com.hubspot.slack.client.models.blocks.BlockElementLengthLimits; import java.util.Collections; import java.util.List; import java.util.Optional; import org.immutables.value.Value; +import org.immutables.value.Value.Check; public interface MessageParams extends HasChannel { Optional getText(); @@ -17,4 +21,24 @@ public interface MessageParams extends HasChannel { default List getBlocks() { return Collections.emptyList(); } + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + Optional getMarkdownText(); + + @Check + default void check() { + getMarkdownText() + .ifPresent(markdown -> { + Preconditions.checkState( + markdown.length() < BlockElementLengthLimits.MAX_MARKDOWN_LENGTH.getLimit(), + "Markdown text length exceeds the limit of " + + BlockElementLengthLimits.MAX_MARKDOWN_LENGTH.getLimit() + + " characters" + ); + Preconditions.checkState( + getText().isEmpty() && getBlocks().isEmpty(), + "Cannot provide text or blocks when providing markdown text" + ); + }); + } } diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/MetadataIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/MetadataIF.java new file mode 100644 index 00000000..dc8230f7 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/MetadataIF.java @@ -0,0 +1,19 @@ +package com.hubspot.slack.client.models; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Map; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface MetadataIF { + @Parameter(order = 0) + String getEventType(); + + @Parameter(order = 1) + Map getEventPayload(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/Block.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/Block.java index beeedf4f..17e1e3a2 100644 --- a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/Block.java +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/Block.java @@ -22,6 +22,9 @@ @JsonSubTypes.Type(value = Image.class, name = Image.TYPE), @JsonSubTypes.Type(value = Input.class, name = Input.TYPE), @JsonSubTypes.Type(value = Section.class, name = Section.TYPE), + @JsonSubTypes.Type(value = Markdown.class, name = Markdown.TYPE), + @JsonSubTypes.Type(value = RichText.class, name = RichText.TYPE), + @JsonSubTypes.Type(value = Video.class, name = Video.TYPE), } ) @JsonInclude(JsonInclude.Include.NON_EMPTY) diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/BlockElementLengthLimits.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/BlockElementLengthLimits.java index b9f9efc2..aafc753a 100644 --- a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/BlockElementLengthLimits.java +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/BlockElementLengthLimits.java @@ -11,7 +11,10 @@ public enum BlockElementLengthLimits { MAX_OPTION_GROUP_LABEL_LENGTH(75), MAX_OPTION_VALUE_LENGTH(75), MAX_CHECKBOXES_NUMBER(10), - MAX_RADIO_BUTTONS_NUMBER(10); + MAX_RADIO_BUTTONS_NUMBER(10), + MAX_VIDEO_AUTHOR_NAME_LENGTH(50), + MAX_VIDEO_DESCRIPTION_LENGTH(200), + MAX_MARKDOWN_LENGTH(12000); private final int limit; diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/MarkdownIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/MarkdownIF.java new file mode 100644 index 00000000..d8090d8d --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/MarkdownIF.java @@ -0,0 +1,50 @@ +package com.hubspot.slack.client.models.blocks; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.google.common.base.Preconditions; +import com.hubspot.immutables.style.HubSpotStyle; +import org.immutables.value.Value.Check; +import org.immutables.value.Value.Derived; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public interface MarkdownIF extends Block { + String TYPE = "markdown"; + + /** + * The type of block. For a markdown block, type is always markdown. + *

+ * Type: String + *
+ * Required: true + */ + @Override + @Derived + default String getType() { + return TYPE; + } + + /** + * The standard markdown-formatted text. Limit 12,000 characters max. + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getText(); + + @Check + default void check() { + Preconditions.checkState( + getText().length() < BlockElementLengthLimits.MAX_MARKDOWN_LENGTH.getLimit(), + "Text length must be less than " + + BlockElementLengthLimits.MAX_MARKDOWN_LENGTH.getLimit() + + " characters" + ); + } +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/RichTextIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/RichTextIF.java new file mode 100644 index 00000000..a3ef8085 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/RichTextIF.java @@ -0,0 +1,33 @@ +package com.hubspot.slack.client.models.blocks; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import com.hubspot.slack.client.models.blocks.elements.richtext.RichTextBlock; +import java.util.List; +import org.immutables.value.Value.Derived; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextIF extends Block { + String TYPE = "rich_text"; + + @Override + @Derived + default String getType() { + return TYPE; + } + + /** + * An array of rich text objects - rich_text_section, rich_text_list, rich_text_preformatted, and rich_text_quote. + *

+ * Type: Object[] (List of RichTextBlock) + *
+ * Required: true + */ + @Parameter + List getElements(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/VideoIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/VideoIF.java new file mode 100644 index 00000000..2048120c --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/VideoIF.java @@ -0,0 +1,162 @@ +package com.hubspot.slack.client.models.blocks; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.google.common.base.Preconditions; +import com.hubspot.immutables.style.HubSpotStyle; +import com.hubspot.slack.client.models.blocks.objects.Text; +import com.hubspot.slack.client.models.blocks.objects.TextType; +import java.util.Optional; +import org.immutables.value.Value.Check; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface VideoIF extends Block { + String TYPE = "video"; + + @Override + default String getType() { + return TYPE; + } + + /** + * A tooltip for the video. Required for accessibility + *

+ * Type: String + *
+ * Required: true + */ + @Parameter(order = 0) + String getAltText(); + + /** + * Author name to be displayed. Must be less than 50 characters. + *

+ * Type: String + *
+ * Required: false + */ + Optional getAuthorName(); + + /** + * Description for video in the form of a text object that must have type of plain_text. text within must be less than 200 characters. + *

+ * Type: Object (Text) + *
+ * Required: false (preferred) + */ + Optional getDescription(); + + /** + * Icon for the video provider, e.g. YouTube icon. + *

+ * Type: String + *
+ * Required: false + */ + Optional getProviderIconUrl(); + + /** + * The originating application or domain of the video, e.g. YouTube + *

+ * Type: String + *
+ * Required: false + */ + Optional getProviderName(); + + /** + * Video title in the form of a text object that must have type of plain_text. text within must be less than 200 characters. + *

+ * Type: Object (Text) + *
+ * Required: true + */ + @Parameter(order = 1) + Text getTitle(); + + /** + * Hyperlink for the title text. Must correspond to the non-embeddable URL for the video. Must go to an HTTPS URL. + *

+ * Type: String + *
+ * Required: false (preferred) + */ + Optional getTitleUrl(); + + /** + * The thumbnail image URL + *

+ * Type: String + *
+ * Required: true + */ + @Parameter(order = 2) + String getThumbnailUrl(); + + /** + * The URL to be embedded. Must match any existing unfurl domains within the app and point to a HTTPS URL. + *

+ * Type: String + *
+ * Required: true + */ + @Parameter(order = 3) + String getVideoUrl(); + + @Check + default void check() { + getAuthorName() + .ifPresent(name -> + Preconditions.checkState( + name.length() < + BlockElementLengthLimits.MAX_VIDEO_AUTHOR_NAME_LENGTH.getLimit(), + "Author name must be less than " + + BlockElementLengthLimits.MAX_VIDEO_AUTHOR_NAME_LENGTH.getLimit() + + " characters" + ) + ); + getDescription() + .ifPresent(description -> { + Preconditions.checkState( + description.getType() == TextType.PLAIN_TEXT, + "The description type of a Video block must be plain_text" + ); + Preconditions.checkState( + description.getText().length() < + BlockElementLengthLimits.MAX_VIDEO_DESCRIPTION_LENGTH.getLimit(), + "Description length must be less than " + + BlockElementLengthLimits.MAX_VIDEO_DESCRIPTION_LENGTH.getLimit() + + " characters" + ); + }); + + Preconditions.checkState( + getTitle().getType() == TextType.PLAIN_TEXT, + "The title type of a Video block must be plain_text" + ); + Preconditions.checkState( + getTitle().getText().length() < + BlockElementLengthLimits.MAX_VIDEO_DESCRIPTION_LENGTH.getLimit(), + "Title length must be less than " + + BlockElementLengthLimits.MAX_VIDEO_DESCRIPTION_LENGTH.getLimit() + + " characters" + ); + + getTitleUrl() + .ifPresent(url -> + Preconditions.checkState( + url.toLowerCase().startsWith("https://"), + "Title url must go to a HTTPS URL" + ) + ); + + Preconditions.checkState( + getVideoUrl().toLowerCase().startsWith("https://"), + "Video url must go to a HTTPS URL" + ); + } +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/BroadcastRange.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/BroadcastRange.java new file mode 100644 index 00000000..30b0b8d0 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/BroadcastRange.java @@ -0,0 +1,32 @@ +package com.hubspot.slack.client.models.blocks.elements; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.hubspot.slack.client.enums.EnumIndex; +import com.hubspot.slack.client.enums.UnmappedKeyException; +import java.util.Optional; + +public enum BroadcastRange { + HERE, + CHANNEL, + EVERYONE; + + private static final EnumIndex INDEX = new EnumIndex<>( + BroadcastRange.class, + BroadcastRange::key + ); + + @JsonCreator + public static BroadcastRange get(String key) throws UnmappedKeyException { + return INDEX.get(key.toLowerCase()); + } + + public static Optional find(String key) { + return INDEX.find(key.toLowerCase()); + } + + @JsonValue + public String key() { + return name().toLowerCase(); + } +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/ListStyle.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/ListStyle.java new file mode 100644 index 00000000..86b5ac9b --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/ListStyle.java @@ -0,0 +1,31 @@ +package com.hubspot.slack.client.models.blocks.elements; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.hubspot.slack.client.enums.EnumIndex; +import com.hubspot.slack.client.enums.UnmappedKeyException; +import java.util.Optional; + +public enum ListStyle { + BULLET, + ORDERED; + + private static final EnumIndex INDEX = new EnumIndex<>( + ListStyle.class, + ListStyle::key + ); + + @JsonCreator + public static ListStyle get(String key) throws UnmappedKeyException { + return INDEX.get(key.toLowerCase()); + } + + public static Optional find(String key) { + return INDEX.find(key.toLowerCase()); + } + + @JsonValue + public String key() { + return name().toLowerCase(); + } +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextBlock.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextBlock.java new file mode 100644 index 00000000..87b7aec8 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextBlock.java @@ -0,0 +1,26 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.hubspot.slack.client.models.blocks.Block; +import com.hubspot.slack.client.models.blocks.UnknownBlock; + +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + property = "type", + defaultImpl = UnknownBlock.class +) +@JsonSubTypes( + { + @JsonSubTypes.Type(value = RichTextList.class, name = RichTextList.TYPE), + @JsonSubTypes.Type( + value = RichTextPreformatted.class, + name = RichTextPreformatted.TYPE + ), + @JsonSubTypes.Type(value = RichTextQuote.class, name = RichTextQuote.TYPE), + @JsonSubTypes.Type(value = RichTextSection.class, name = RichTextSection.TYPE), + } +) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public interface RichTextBlock extends Block {} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextBroadcastIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextBroadcastIF.java new file mode 100644 index 00000000..3c1d2b65 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextBroadcastIF.java @@ -0,0 +1,30 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import com.hubspot.slack.client.models.blocks.elements.BroadcastRange; +import org.immutables.value.Value; +import org.immutables.value.Value.Parameter; + +@Value.Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextBroadcastIF extends RichTextElement { + String TYPE = "broadcast"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The range of the broadcast; value can be here, channel, or everyone. Using here notifies only the active members of a channel; channel notifies all members of a channel; everyone notifies every person in the #general channel. + *

+ * Type: String (enum BroadcastRange) + *
+ * Required: true + */ + @Parameter + BroadcastRange getRange(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextChannelIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextChannelIF.java new file mode 100644 index 00000000..15b9e9dd --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextChannelIF.java @@ -0,0 +1,39 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value; +import org.immutables.value.Value.Parameter; + +@Value.Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextChannelIF extends RichTextElement { + String TYPE = "channel"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The ID of the channel to be mentioned. + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getChannelId(); + + /** + * An object of six optional boolean properties that dictate style: bold, italic, strike, highlight, client_highlight, and unlink. + *

+ * Type: Object (RichTextStyle) + *
+ * Required: false + */ + Optional getStyle(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextColorIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextColorIF.java new file mode 100644 index 00000000..9c1e5283 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextColorIF.java @@ -0,0 +1,30 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import static org.immutables.value.Value.Immutable; +import static org.immutables.value.Value.Parameter; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextColorIF extends RichTextElement { + String TYPE = "color"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The hex value for the color. + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getValue(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextDateIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextDateIF.java new file mode 100644 index 00000000..24d80d1e --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextDateIF.java @@ -0,0 +1,73 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextDateIF extends RichTextElement { + String TYPE = "date"; + + @Override + default String getType() { + return TYPE; + } + + /** + * A Unix timestamp for the date to be displayed in seconds. + *

+ * Type: Number + *
+ * Required: true + */ + @Parameter(order = 0) + long getTimestamp(); + + /** + * A template string containing curly-brace-enclosed tokens to substitute your provided timestamp. + *
    + *
  • {day_divider_pretty}: Shows today, yesterday or tomorrow if applicable. Otherwise, if the date is in current year, uses the {date_long} format without the year. Otherwise, falls back to using the {date_long} format.
  • + *
  • {date_num}: Shows date as YYYY-MM-DD.
  • + *
  • {date_slash}: Shows date as DD/MM/YYYY (subject to locale preferences).
  • + *
  • {date_long}: Shows date as a long-form sentence including day-of-week, e.g. Monday, December 23rd, 2013.
  • + *
  • {date_long_full}: Shows date as a long-form sentence without day-of-week, e.g. August 9, 2020.
  • + *
  • {date_long_pretty}: Shows yesterday, today or tomorrow, otherwise uses the {date_long} format.
  • + *
  • {date}: Same as {date_long_full} but without the year.
  • + *
  • {date_pretty}: Shows today, yesterday or tomorrow if applicable, otherwise uses the {date} format.
  • + *
  • {date_short}: Shows date using short month names without day-of-week, e.g. Aug 9, 2020.
  • + *
  • {date_short_pretty}: Shows today, yesterday or tomorrow if applicable, otherwise uses the {date_short} format.
  • + *
  • {time}: Depending on user preferences, shows just the time-of-day portion of the timestamp using either 12 or 24 hour clock formats, e.g. 2:34 PM or 14:34.
  • + *
  • {time_secs}: Depending on user preferences, shows just the time-of-day portion of the timestamp using either 12 or 24 hour clock formats, including seconds, e.g. 2:34:56 PM or 14:34:56.
  • + *
  • {ago}: A human-readable period of time, e.g. 3 minutes ago, 4 hours ago, 2 days ago.
  • + *
+ *

+ * Type: String + *
+ * Required: true + */ + @Parameter(order = 1) + String getFormat(); + + /** + * URL to link the entire format string to. + *

+ * Type: String + *
+ * Required: false + */ + Optional getUrl(); + + /** + * Text to display in place of the date should parsing, formatting or displaying fail. + *

+ * Type: String + *
+ * Required: false + */ + Optional getFallback(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextElement.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextElement.java new file mode 100644 index 00000000..62c61540 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextElement.java @@ -0,0 +1,27 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.hubspot.slack.client.models.blocks.UnknownBlock; + +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + property = "type", + defaultImpl = UnknownBlock.class +) +@JsonSubTypes( + { + @JsonSubTypes.Type(value = RichTextBroadcast.class, name = RichTextBroadcast.TYPE), + @JsonSubTypes.Type(value = RichTextColor.class, name = RichTextColor.TYPE), + @JsonSubTypes.Type(value = RichTextChannel.class, name = RichTextChannel.TYPE), + @JsonSubTypes.Type(value = RichTextDate.class, name = RichTextDate.TYPE), + @JsonSubTypes.Type(value = RichTextEmoji.class, name = RichTextEmoji.TYPE), + @JsonSubTypes.Type(value = RichTextLink.class, name = RichTextLink.TYPE), + @JsonSubTypes.Type(value = RichTextText.class, name = RichTextText.TYPE), + @JsonSubTypes.Type(value = RichTextUser.class, name = RichTextUser.TYPE), + @JsonSubTypes.Type(value = RichTextUserGroup.class, name = RichTextUserGroup.TYPE), + } +) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public interface RichTextElement extends RichTextBlock {} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextEmojiIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextEmojiIF.java new file mode 100644 index 00000000..e2971150 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextEmojiIF.java @@ -0,0 +1,39 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextEmojiIF extends RichTextElement { + String TYPE = "emoji"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The name of the emoji; i.e. "wave" or "wave::skin-tone-2". + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getName(); + + /** + * Represents the unicode code point of the emoji, where applicable. + *

+ * Type: String + *
+ * Required: false + */ + Optional getUnicode(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextLinkIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextLinkIF.java new file mode 100644 index 00000000..3dd619b6 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextLinkIF.java @@ -0,0 +1,57 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextLinkIF extends RichTextElement { + String TYPE = "link"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The link's url + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getUrl(); + + /** + * The text shown to the user (instead of the url). If no text is provided, the url is used. + *

+ * Type: String + *
+ * Required: false + */ + Optional getText(); + + /** + * Indicates whether the link is safe. + *

+ * Type: Boolean + *
+ * Required: false + */ + Optional getUnsafe(); + + /** + * An object containing four boolean properties: bold, italic, strike, and code. + *

+ * Type: RichTextSimpleStyle + *
+ * Required: false + */ + Optional getStyle(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextListIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextListIF.java new file mode 100644 index 00000000..a96faba3 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextListIF.java @@ -0,0 +1,68 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import com.hubspot.slack.client.models.blocks.elements.ListStyle; +import java.util.List; +import java.util.Optional; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextListIF { + String TYPE = "rich_text_list"; + + default String getType() { + return TYPE; + } + + /** + * Either bullet or ordered, the latter meaning a numbered list. + *

+ * Type: String (enum of ListStyle) + *
+ * Required: true + */ + @Parameter(order = 0) + ListStyle getStyle(); + + /** + * An array of rich_text_section objects containing two properties: type, which is "rich_text_section", and elements, which is an array of rich text element objects. + *

+ * Type: Object[] (List of RichTextSection) + *
+ * Required: true + */ + @Parameter(order = 1) + List getElements(); + + /** + * Number of pixels to indent the list. + *

+ * Type: Number + *
+ * Required: false + */ + Optional getIndent(); + + /** + * Number of pixels to offset the list. + *

+ * Type: Integer + *
+ * Required: false + */ + Optional getOffset(); + + /** + * Number of pixels of border thickness. + *

+ * Type: Integer + *
+ * Required: false + */ + Optional getBorder(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextPreformattedIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextPreformattedIF.java new file mode 100644 index 00000000..0d19de6b --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextPreformattedIF.java @@ -0,0 +1,40 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.List; +import java.util.Optional; +import org.immutables.value.Value; +import org.immutables.value.Value.Parameter; + +@Value.Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextPreformattedIF extends RichTextBlock { + String TYPE = "rich_text_preformatted"; + + @Override + default String getType() { + return TYPE; + } + + /** + * An array of rich text elements. + *

+ * Type: Object[] (List of RichTextElement) + *
+ * Required: true + */ + @Parameter + List getElements(); + + /** + * Number of pixels of border thickness. + *

+ * Type: Integer + *
+ * Required: false + */ + Optional getBorder(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextQuoteIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextQuoteIF.java new file mode 100644 index 00000000..ea675f82 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextQuoteIF.java @@ -0,0 +1,40 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.List; +import java.util.Optional; +import org.immutables.value.Value; +import org.immutables.value.Value.Parameter; + +@Value.Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextQuoteIF extends RichTextBlock { + String TYPE = "rich_text_quote"; + + @Override + default String getType() { + return TYPE; + } + + /** + * An array of rich text elements. + *

+ * Type: Object[] (List of RichTextElement) + *
+ * Required: true + */ + @Parameter + List getElements(); + + /** + * Number of pixels of border thickness. + *

+ * Type: Integer + *
+ * Required: false + */ + Optional getBorder(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextSectionIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextSectionIF.java new file mode 100644 index 00000000..3c3f75d3 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextSectionIF.java @@ -0,0 +1,23 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.List; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextSectionIF extends RichTextBlock { + String TYPE = "rich_text_section"; + + @Override + default String getType() { + return TYPE; + } + + @Parameter + List getElements(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextSimpleStyleIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextSimpleStyleIF.java new file mode 100644 index 00000000..c92fe506 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextSimpleStyleIF.java @@ -0,0 +1,20 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextSimpleStyleIF { + Optional getBold(); + + Optional getItalic(); + + Optional getStrike(); + + Optional getCode(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextStyleIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextStyleIF.java new file mode 100644 index 00000000..af9a29a5 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextStyleIF.java @@ -0,0 +1,18 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextStyleIF extends RichTextSimpleStyleIF { + Optional getHighlight(); + + Optional getClientHighlight(); + + Optional getUnlink(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextTextIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextTextIF.java new file mode 100644 index 00000000..39df49c6 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextTextIF.java @@ -0,0 +1,39 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextTextIF extends RichTextElement { + String TYPE = "text"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The text shown to the user + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getText(); + + /** + * An object containing four boolean fields, none of which are required: bold, italic, strike, and code. + *

+ * Type: Object (RichTextSimpleStyle) + *
+ * Required: false + */ + Optional getStyle(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextUserGroupIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextUserGroupIF.java new file mode 100644 index 00000000..3f5e9075 --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextUserGroupIF.java @@ -0,0 +1,39 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextUserGroupIF extends RichTextElement { + String TYPE = "usergroup"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The ID of the user group to be mentioned + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getUsergroupId(); + + /** + * An object of six optional boolean properties that dictate style: bold, italic, strike, highlight, client_highlight, and unlink. + *

+ * Type: Object (RichTextStyle) + *
+ * Required: false + */ + Optional getStyle(); +} diff --git a/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextUserIF.java b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextUserIF.java new file mode 100644 index 00000000..114dd3ca --- /dev/null +++ b/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/elements/richtext/RichTextUserIF.java @@ -0,0 +1,39 @@ +package com.hubspot.slack.client.models.blocks.elements.richtext; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.hubspot.immutables.style.HubSpotStyle; +import java.util.Optional; +import org.immutables.value.Value.Immutable; +import org.immutables.value.Value.Parameter; + +@Immutable +@HubSpotStyle +@JsonNaming(SnakeCaseStrategy.class) +public interface RichTextUserIF extends RichTextElement { + String TYPE = "user"; + + @Override + default String getType() { + return TYPE; + } + + /** + * The ID of the user to be mentioned + *

+ * Type: String + *
+ * Required: true + */ + @Parameter + String getUserId(); + + /** + * An object of six optional boolean properties that dictate style: bold, italic, strike, highlight, client_highlight, and unlink. + *

+ * Type: Object (RichTextStyle) + *
+ * Required: false + */ + Optional getStyle(); +} diff --git a/slack-base/src/test/resources/unknown_blocks.json b/slack-base/src/test/resources/unknown_blocks.json index cfb40d7a..476854e2 100644 --- a/slack-base/src/test/resources/unknown_blocks.json +++ b/slack-base/src/test/resources/unknown_blocks.json @@ -1,6 +1,6 @@ [ { - "type": "rich_text", + "type": "unimplemented_block", "elements": [ { "type": "rich_text_section", diff --git a/slack-java-client/src/main/java/com/hubspot/slack/client/SlackClient.java b/slack-java-client/src/main/java/com/hubspot/slack/client/SlackClient.java index d09ac57c..19527234 100644 --- a/slack-java-client/src/main/java/com/hubspot/slack/client/SlackClient.java +++ b/slack-java-client/src/main/java/com/hubspot/slack/client/SlackClient.java @@ -397,9 +397,10 @@ CompletableFuture> addReaction( // files /** - * This method is being sunset on March 11, 2025 + * This method is being sunset on November 12, 2025 * @deprecated use {@link #getUploadURLExternal(GetUploadUrlExternalParams)} and {@link #completeUploadExternal(CompleteUploadExternalParams)} * @see Sunset details + * @see Sunset extension details */ @Deprecated CompletableFuture> uploadFile(