Code Monkey home page Code Monkey logo

slack-client's Introduction

slack-client

license GitHub last commit Build Status GitHub release Maven metadata URI

Overview

An asychronous HTTP client wrapping Slack's RPC-style web api. Provides an extensible API with builder-style parameters and responses, allowing you to focus on your interactions with users, rather than your interactions with Slack. Notably, we:

  • Implement most of Slack's web API
  • Actively maintain this project
  • Provide per-method in-memory rate limiting so you don't have to worry about overwhelming slack from a single process
  • Expose highly configurable hooks to allow custom rate limiting, method filtering, and debugging in an extensible way

Breaking Changes

NOTICE:

The original web API method for uploading files to Slack, files.upload, is being sunset on March 11, 2025. See details

On October 18th 2019, Slack will stop supporting the replies thread on a Message returned from the conversations.replies endpoint as well as any places that use LiteMessage.

Due to this, we are deprecating getReplies() on LiteMessage It will return the data as long as Slack still returns it, bue when they stop, we will just return an empty array.

More context in the April 2019 changelog

You can continue to use an older version of this client until October 18th, at which time you'll need to upgrade to the latest.

Maintenance

Like most APIs, deprecations and modifications that we'll call "breaking changes" will occur on Slack's web API. General guidelines on detecting and handling "breaking changes" can be found here

Features

We currently support:

auth

  • auth.test
  • auth.revoke

channels

  • channels.history
  • channels.info
  • channels.kick (kickUserFromChannel)
  • channels.list
  • channels.replies (findReplies)

chat

  • chat.delete
  • chat.getPermalink
  • chat.postEphemeral
  • chat.postMessage
  • chat.update
  • chat.scheduleMessage
  • chat.deleteScheduledMessage
  • chat.scheduledMessages.list

conversations

  • conversations.archive
  • conversations.create
  • conversations.history
  • conversations.info
  • conversations.invite
  • conversations.list
  • conversations.members
  • conversations.open
  • conversations.unarchive
  • conversations.setTopic
  • conversations.setPurpose

dialog

  • dialog.open

files

  • files.upload
  • files.getUploadURLExternal
  • files.completeUploadExternal
  • files.sharedPublicURL

groups

  • groups.kick (kickUserFromGroup)
  • groups.list
  • groups.replies (findReplies)

im

  • im.open

reactions

  • reactions.add

search

  • search.messages

team

  • team.info

usergroups

  • usergroups.create
  • usergroups.disable
  • usergroups.enable
  • usergroups.list
  • usergroups.update

usergroups.users

  • usergroups.users.update

users

  • users.conversations
  • users.info (findUser)
  • users.list
  • users.lookupByEmail

views

  • views.open
  • views.update
  • views.push
  • views.publish

Utility Methods

  • getConversationByName
  • getChannelByName

Migration

  • migration.exchange

We happily welcome any PRs for APIs that haven't yet been implemented!

Usage

To use with Maven-based projects, add the following dependencies::

<dependency>
  <groupId>com.hubspot.slack</groupId>
  <artifactId>slack-base</artifactId>
  <version>{latest version}</version>
</dependency>
<dependency>
  <groupId>com.hubspot.slack</groupId>
  <artifactId>slack-java-client</artifactId>
  <version>{latest  version}</version>
</dependency>

Latest version can be seen here, on Maven central.

Setting up Guice

Install the SlackClientModule in the Guice module you want to use to talk to slack.

public class MyFancyModule extends AbstractModule {
  @Override
  protected void configure() {
    install(new SlackClientModule());
  }
}

Finally inject the factory where you want to build the client:

public class MySlacker {
  private final SlackClient slackClient;
  
  
  public MySlacker(
      SlackWebClient.Factory clientFactory
  ) {
    this.slackClient = clientFactory.build(
        SlackClientRuntimeConfig.builder()
          .setTokenSupplier(() -> "your token here")
          // ... all your configuration here
          .build()
    );
  }
  
  // then just use the client!
}

Using the Client

If you're not familiar with Java 8's CompletableFuture API, know that you can transform this client from an asynchronous one to a synchronous one by calling join on any of the futures returned. To simplify getting started, we've included an example module with some common tasks to give you a feel for how you can interact with the client.

Contributors

License

Copyright 2018 HubSpot, Inc.

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.

slack-client's People

Contributors

andybergon avatar axiak avatar aybbr avatar bwehner avatar courtneyadams avatar dependabot[bot] avatar dylanrb123 avatar higityan avatar hs-jenkins-bot avatar jaredstehler avatar johnnyleitrim avatar kecarroll avatar leonidhladii avatar lightbody avatar matush-v avatar mindspin311 avatar mlr46 avatar motnyk avatar nliutyi-hs avatar omotnyk avatar rmarsch avatar rydelaney-hs avatar ssalinas avatar stevie400 avatar szabowexler avatar vtymtsiv avatar wsorenson avatar ykaliukh avatar zklapow avatar zmarushchak-hs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slack-client's Issues

CI checks are falling

Describe the bug
Need to investigate and fix why all new PR checks are falling -
Caused by: java.lang.RuntimeException: Unable to find commits until some tag,
Caused by: org.eclipse.jgit.errors.MissingObjectException: Missing commit 8805e826b967b08812a4bb13d80ddfe1eca9f98b

To Reproduce
Steps to reproduce the behavior:

  1. Create a new PR (or open existsed)
  2. Go to Checks section
  3. Open any of failed CI build details

Expected behavior
New PR checks should be successful

Add topic field to ConversationIF

A follow-up to this issue: #205

There is a "topic" field missing in ConversationIF

Suggestion

Add to ConversationIF:

@JsonProperty("topic")
Optional<Topic> getTopic();

Add TopicIF interface:

@HubSpotStyle
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public interface TopicIF {
    @JsonProperty("value")
    Optional<String> getValue();
    @JsonProperty("creator")
    Optional<String> getCreator();
    @JsonProperty("last_set")
    Optional<Long> getLastSet();
}

P.S. There are more fields missing but my project require only this one.

Expanded TopLevelMessageInteractionResponse

TopLevelMessageInteractionResponse doesn't contain all the fields that Slack supports. Specifically, per these docs:

Within these responses, you can include a message payload. This message payload can be composed according to the same message composition guides as any other, with a few exceptions that we'll explain below.

The main thing missing is, of course, the blocks fields. I'll try to get a patch out soon, but wanted to capture the gap now while it was top of mind.

Messages by bots do not have a user

Describe the bug
When searching, messages written by apps do not have a user set and fail by throwing:

Cannot build Message, some of required attributes are not set [user]

To Reproduce
Steps to reproduce the behavior:

  1. Search for messages in some channel written by an app:
searchMessages(SearchMessagesParams.builder()
                .setQuery("in:#some_channel written by app")
                .build())
                .join()
                .unwrapOrElseThrow()
                .messages
                .matches
                .firstOrNull()
  1. Jackson tries to parse found message:
{
      "iid" : "...",
      "team" : "...",
      "channel" : {
        "id" : "...",
        "is_channel" : true,
        "is_group" : false,
        "is_im" : false,
        "name" : "some_channel",
        "is_shared" : false,
        "is_org_shared" : false,
        "is_ext_shared" : false,
        "is_private" : false,
        "is_mpim" : false,
        "pending_shared" : [ ],
        "is_pending_ext_shared" : false
      },
      "type" : "message",
      "user" : null,
      "username" : "app-name",
      "ts" : "1572520802.000200",
      "text" : "written by an app",
      "permalink" : "..."
    }
  1. Exception is thrown:
Caused by: com.hubspot.immutables.validation.InvalidImmutableStateException: Cannot build Message, some of required attributes are not set [user]
	at com.hubspot.slack.client.models.Message$Builder.checkRequiredAttributes(Message.java:1298)
	at com.hubspot.slack.client.models.Message$Builder.build(Message.java:1251)
	at com.hubspot.slack.client.models.Message.fromJson(Message.java:921)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.fasterxml.jackson.databind.introspect.AnnotatedMethod.call1(AnnotatedMethod.java:114)
	at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator._createUsingDelegate(StdValueInstantiator.java:516)
	... 35 more
Exception in thread "main" java.lang.IllegalStateException: SlackError{type=JSON_PARSING_FAILED, error=_json_parsing_failed}
	at com.hubspot.algebra.Result.lambda$unwrapOrElseThrow$1(Result.java:68)
	at com.hubspot.algebra.Result.lambda$unwrapOrElseThrow$0(Result.java:64)
	at java.util.Optional.orElseThrow(Optional.java:290)
	at com.hubspot.algebra.Result.unwrapOrElseThrow(Result.java:60)
	at com.hubspot.algebra.Result.unwrapOrElseThrow(Result.java:64)
	at com.hubspot.algebra.Result.unwrapOrElseThrow(Result.java:68)

Expected behavior
Does not crash. User shouldn't be required?

Additional context
It's interesting that the message's username is present but not the user. Are they similar?

Message was previously written by the same script using a slack token for the app:

val config = SlackClientRuntimeConfig.builder()
    .setTokenSupplier { slackToken }
    .build()
val slackClient = SlackClientFactory.defaultFactory().build(config)

postMessage(ChatPostMessageParams.builder()
    .setText(message)
    .setChannelId(slackChannel)
    .build())
    .join()
    .unwrapOrElseThrow()

postMessage not working as Slack requires "token" be sent in body instead of the Auth header

Slack Api chat.postMessage endpoint requires token parameter to be sent in body instead of Auth header. This leads to incorrect_arguments error.

To Reproduce
Steps to reproduce the behavior:

  1. Send new message using standard way (see my example below)
    val client = SlackClientFactory.defaultFactory().build(
        SlackClientRuntimeConfig.builder()
            .setTokenSupplier {
                "nomnom"
            }.build()
    )

    val message = ChatPostMessageParams.builder()
        .setChannelId(some channel id")
        .setText("Test")
        .build()

    val future = client.postMessage(
        message
    )

    val result = future.get()
  1. See the result

Expected behavior
Message is sent, ok result is returned

Actual result
No messages are sent, error invalid_arguments is returned

Add support for Header block type for message API

Is your feature request related to a problem? Please describe.

There is a block type which I don't believe is currently available in the hubspot slack-client: Header. If I had to guess, I believe this is because the Header type is a relatively new type. I think it would be useful to add, as it formats a message like a markdown heading, making it easier to read longer messages.

Describe alternatives you've considered
I'm thinking about implementing a Header class directly by extending the Section block and setting its type to always be "Header"

Add fields to ConversationIF

I have to get channel topic, but Conversation model doesn't have this field. I have written a code, but have no idea how to push my branch to repo. Please add these fields or help me with contributing.

Advice requested: HTTP client metrics

Hi there. We're using the Micronaut framework, which has it's own HTTP client and ExecutorService, both of which get nice metrics sent out to our prometheus setup.

This project seems to fall back to it's own ExecutorService + Ning's HTTP client, and as a result I don't have as much visibility when things so sideways.

Do you have any advice on how I should solve this? For another project, I had a place where I could plug in my own HTTP client wrapper + ExecutorService and that worked well. But here it doesn't look like that is the case, though I could be misreading the code.

users.conversations

For my bot in order to post automatically in channels, groups etc I need to fetch all its conversations it has been invited to. For that I'd like to use users.conversations but it seems this method has not been implemented yet.

Any chance we might see that?

Help clients deal with errors

There's a ton of different Slack errors that clients have to deal with. In most cases the particular error isn't important, but the category is. It would be really helpful to know if an error is a client error or a server error. This would let us retry or just fail requests based on the category of error.

@darcatron
@szabowexler

Accsess troubles with private chanels

I use Kotlin code like this:

val chanelIds = slackClient
            .listChannels(ChannelsListParams.builder().build())
            .asSequence()
            .map { it.join().unwrapOrElseThrow() }
            .flatten()
            .map { it.name to it.id }
            .toMap()

and expect to get all channels (private and non-private), but get only public channels in spite of my app has participation in private channel

How to react to Slack Events?

I get the impression from the code that this library is capable of subscribing to, and receiving, events from the Slack API. For example, the MEMBER_JOINED_CHANNEL or MESSAGE events are invaluable to create an interactive bot.

However, I can't work out how to do this. I can't see any code that actually returns events, any way to subscribe to them, or anything like that.

What am I missing? Or is this future functionality?

Cheers

How to set the charset?

Sorry for the stupid question, I'm new to Slack development.
I receive a missing_charset warning in response all the times on SlackClient.postMessage(), and I checked the samples and look everywhere in the code but I don't understand how to set the charset.

My SlackClient instance:

  @Bean
  public SlackClient getSlackClient() {
    SlackClientRuntimeConfig runtimeConfig = SlackClientRuntimeConfig.builder()
      .setTokenSupplier(() -> slackAppToken)
      .build();
    return SlackClientFactory.defaultFactory().build(runtimeConfig);
  }

My postmessage code:

  public static void simplePostMessage(SlackClient slackClient, String channel, String text) {
    try {
      slackClient.postMessage(
        ChatPostMessageParams.builder()
          .setText(text)
          .setChannelId(channel)
          .build())
        .join().unwrapOrElseThrow();
    } catch (Exception e) {
      log.error("slackClient.postMessage", e);
    }
  }

Thank you.

JSON parsing error in SlackWebClient.shareFilePublically method

Describe the bug
I'm calling SlackWebClient.shareFilePublically() method which executes successfully (I get correct JSON in the log), however it fails with JSON parsing error:

2019-01-28 13:26:55 +0100 [ERROR] from com.hubspot.slack.client.interceptors.http.DefaultHttpResponseDebugger in NioHttpClient-Callback-1 - REQ<1> [files_sharedPublicURL]: Failed interaction
POST https://slack.com/api/files.sharedPublicURL
------------------------------------------
Authorization = Bearer xox...269dContent-Type = application/json
------------------------------------------
{
  "file" : "FFS6VUKPG"
}
------------------------------------------
Content-Type = application/json; charset=utf-8
Connection = keep-alive
Date = Mon, 28 Jan 2019 12:26:55 GMT
Server = Apache
Expires = Mon, 26 Jul 1997 05:00:00 GMT
X-Content-Type-Options = nosniff
Pragma = no-cache
Vary = Accept-Encoding
X-Accepted-OAuth-Scopes = files:write:user
X-OAuth-Scopes = identify,bot,commands,channels:history,files:write:user
Cache-Control = private, no-cache, no-store, must-revalidate
X-XSS-Protection = 0
X-Slack-Req-Id = 1022cec4-d6a2-4b67-bb52-b727c610b5e6
Strict-Transport-Security = max-age=31536000; includeSubDomains; preload
Referrer-Policy = no-referrer
Access-Control-Allow-Origin = *
X-Via = haproxy-www-xkzu
X-Cache = Miss from cloudfront
Via = 1.1 59574f77a7cf2d23d64904db278e5711.cloudfront.net (CloudFront)
X-Amz-Cf-Id = Rc75U-ml_lCJCy9rPy7fP2MbP51xlAtm_OYxeFoaZZYM_qqoamtWuQ==
Content-Length = 2380
------------------------------------------
{
  "ok" : true,
  "file" : {
    "id" : "FFS6VUKPG",
    "created" : 1548678406,
    "timestamp" : 1548678406,
    "name" : "1check8-02.jpg",
    "title" : "1check8-02.jpg",
    "mimetype" : "image/jpeg",
    "filetype" : "jpg",
    "pretty_type" : "JPEG",
    "user" : "UCXD8T8SG",
    "editable" : false,
    "size" : 372643,
    "mode" : "hosted",
    "is_external" : false,
    "external_type" : "",
    "is_public" : true,
    "public_url_shared" : true,
    "display_as_bot" : false,
    "username" : "",
    "url_private" : "https://files.slack.com/files-pri/T4J7W5WQP-FFS6VUKPG/1check8-02.jpg",
    "url_private_download" : "https://files.slack.com/files-pri/T4J7W5WQP-FFS6VUKPG/download/1check8-02.jpg",
    "thumb_64" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_64.jpg",
    "thumb_80" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_80.jpg",
    "thumb_360" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_360.jpg",
    "thumb_360_w" : 206,
    "thumb_360_h" : 360,
    "thumb_480" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_480.jpg",
    "thumb_480_w" : 275,
    "thumb_480_h" : 480,
    "thumb_160" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_160.jpg",
    "thumb_720" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_720.jpg",
    "thumb_720_w" : 412,
    "thumb_720_h" : 720,
    "thumb_800" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_800.jpg",
    "thumb_800_w" : 800,
    "thumb_800_h" : 1399,
    "thumb_960" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_960.jpg",
    "thumb_960_w" : 549,
    "thumb_960_h" : 960,
    "thumb_1024" : "https://files.slack.com/files-tmb/T4J7W5WQP-FFS6VUKPG-e3ee1e4b2d/1check8-02_1024.jpg",
    "thumb_1024_w" : 586,
    "thumb_1024_h" : 1024,
    "image_exif_rotation" : 1,
    "original_w" : 1356,
    "original_h" : 2371,
    "permalink" : "https://1checkin.slack.com/files/UCXD8T8SG/FFS6VUKPG/1check8-02.jpg",
    "permalink_public" : "https://slack-files.com/T4J7W5WQP-FFS6VUKPG-9ce40500a8",
    "comments_count" : 0,
    "is_starred" : false,
    "shares" : {
      "public" : {
        "CEV3N9STA" : [ {
          "reply_users" : [ "UCXD8T8SG", "U00", "U4GSMANP3" ],
          "reply_users_count" : 3,
          "reply_count" : 23,
          "ts" : "1548678414.003300",
          "thread_ts" : "1548266695.002100",
          "latest_reply" : "1548678414.003300",
          "channel_name" : "chat-staging",
          "team_id" : "T4J7W5WQP"
        } ]
      }
    },
    "channels" : [ "CEV3N9STA" ],
    "groups" : [ ],
    "ims" : [ ]
  },
  "warning" : "missing_charset",
  "response_metadata" : {
    "warnings" : [ "missing_charset" ]
  }
}
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'jpg' into a subtype of [simple type, class com.hubspot.slack.client.models.files.SlackFile]: known type ids = [SlackFile, csv, gif, text]
 at [Source: N/A; line: -1, column: -1] (through reference chain: com.hubspot.slack.client.models.response.files.FilesSharedPublicUrlResponse$Json["file"])
        at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:42)
        at com.fasterxml.jackson.databind.DeserializationContext.unknownTypeIdException(DeserializationContext.java:1490)
        at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownTypeId(DeserializationContext.java:1170)
        at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleUnknownTypeId(TypeDeserializerBase.java:282)
        at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:156)
        at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:112)
        at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:97)
        at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:209)
        at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:502)
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:104)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:178)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:150)
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1187)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:314)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148)
        at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3786)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2115)
        at com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:2612)
        at com.hubspot.slack.client.SlackWebClient.lambda$executeLoggedAs$16(SlackWebClient.java:918)
        at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:602)
        at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577)
        at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
        at java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:561)
        at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:580)
        at java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:442)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

To Reproduce
Steps to reproduce the behavior:

  1. Call SlackWebClient.shareFilePublically with params indicating fileId
  2. See error in log

Expected behavior
No error in log

Additional context
The actual public permalink JSON result is working fine!

OptionOrOptionGroup cannot be deserialized

Describe the bug
When sending a payload that contains BlockKit with a StaticSelectMenu or StaticMultiSelectMenu (and likely ExternalMultiSelectMenu though I haven't tested that), the request goes through fine but deserializing the response (if it includes the view just sent) will fail with an error like so:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.hubspot.slack.client.models.blocks.objects.OptionOrOptionGroup` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.hubspot.slack.client.models.response.views.ModalViewCommandResponse$Json["view"]->com.hubspot.slack.client.models.response.views.ModalViewResponse$Json["blocks"]->java.util.ArrayList[2]->com.hubspot.slack.client.models.blocks.Section$Json["accessory"]->com.hubspot.slack.client.models.blocks.elements.StaticSelectMenu$Json["initial_option"])

It appears Jackson needs a bit of extra coaching to be told how to deserialize the OptionOrOptionGroup fields in those objects. The pattern used elsewhere (ex: @JsonSubTypes) doesn't quite work here since there isn't a clear type indicator. Unfortunately, my Jackson skills aren't strong enough to get you a PR right now, so logging this bug until I gain said skills :)

Thanks!

Authorization token query parameter is no longer supported for new Slack apps

The Slack API no longer supports the authorization token query parameter for bots created since the 24th Februrary (https://api.slack.com/changelog/2020-11-no-more-tokens-in-querystrings-for-newly-created-apps).

This project seems to still use this query parameter which is causing requests such as conversations.list to fail with an invalid_auth error.

I've only just found the cause of the issue but can't see an obvious way of configuring how the token is sent in a request using the SlackClientRuntimeConfig.

getReplies() deprecated method is still used in getConversationHistory()

Describe the bug
Using the latest release (1.4), I got error about the getReplies() deprecation when using getConversationHistory().
I do not need replies and there is no way to disable the call of getReplies().

To Reproduce
Steps to reproduce the behavior:

  1. call getConversationHistory() with setChannelId("XXXX")
  2. Run
  3. See error:

2020-01-23 ERROR [NioHttpClient-Callback-0] c.h.s.c.m.LiteMessage : Method getReplies() is now deprecated. Slack will stop supporting completely on Oct 18th 2019

Expected behavior
1 Don't use a deprecated method
2 Let choose whether to retrieve the replies or not

ts is required by SlackEvent model, but Slack does not set ts on all events

Describe the bug
ts is required by the SlackEvent interface, but slack only sets ts on some events, such as messages sent, while not on others, such as channel_created

To Reproduce
Try to parse a channel_created to a SlackEvent

Expected behavior
All slack events JSON should be parseable to SlackEvent

Additional context
Note: Fixing this would be a breaking change, as it would change the SlackEvent interface
Edit: Actually, this could be fixed in a non-breaking way by making ts nullable, which would be uglier but would fix this bug
See: https://api.slack.com/events-api#event_type_structure
https://api.slack.com/events/channel_created
https://api.slack.com/events/message (which DOES include ts)

Example channel_created message:

{
  "token": "uWopedqK86MJfjUeq8v9pUAD",
  "team_id": "TBQPW3FH6",
  "api_app_id": "A945JNH24",
  "event": {
    "type": "channel_created",
    "channel": {
      "id": "CCXF9BDV1",
      "is_channel": true,
      "name": "test",
      "name_normalized": "test",
      "created": 1537452804,
      "creator": "UBRFHDFGA",
      "is_shared": false,
      "is_org_shared": false
    },
    "event_ts": "1537452804.000100"
  },
  "type": "event_callback",
  "event_id": "EvCXCPK952",
  "event_time": 1537452804,
  "authed_users": [
    "UBRFHDFGA"
  ]
}

Add compile-time checks for length of text in Section Blocks

So e.g. https://github.com/HubSpot/slack-client/blob/master/slack-base/src/main/java/com/hubspot/slack/client/models/blocks/SectionIF.java

...I've been running into limits with section blocks needing to be <= 3000 characters long (link to slack api with this limitation described). I was wondering if it would be a good idea to add a Precondition in the check method, to make sure that the text field in our Section class is also <= 3000 characters. That way, we can know during compile time whether our section blocks have invalidly long text. Does that sound like a good addition to this project?

Originally posted by @richardxu100 in #190 (comment)

Post message IllegalStateException

I tried to post a message to a private channel (conversation) and set the text, but I get an illegal state exception:

ERROR com.hubspot.slack.client.interceptors.http.DefaultHttpResponseDebugger: REQ<7> [chat_postMessage]: Failed interaction

IllegalStateException: SlackError{type=UNKNOWN, error=invalid_arguments}

{
  "ok" : false,
  "error" : "invalid_arguments",
  "deprecated_argument" : "as_user",
  "warning" : "missing_charset",
  "response_metadata" : {
    "warnings" : [ "missing_charset" ]
  }
}

Here is what I tried:

Result<ChatPostMessageResponse, SlackError> postResult = slackClient.postMessage(
         ChatPostMessageParams.builder()
                   .setText("hey there")
                   .setChannelId(getChannelId(channelName))
                   .build()
).join();

I've also tried passing in the channelName as the slack api suggests and followed the examples in this library but still gave me the same error.

Could anyone please take a look?

BlockActionsIF.channel should not be null

BlockActionsIF currently defines the channel property with a default null value for backwards compatibility with older code. In fact, my experience with BlockActions is that the payload does populate a channel object (with id, name).

Slack payloads have changed, breaking deserialization

It appears that this got released in the last few hours, and it's causing problems for parts of our application:

https://api.slack.com/changelog/2020-09-full-state-on-view-submisson-and-block-actions

Specifically, for us when we deserialize SlackInteractiveCallback and in particular BlockActions, the new state data causes errors like this:

com.fasterxml.jackson.databind.JsonMappingException: blockElementValue (through reference chain: 
com.hubspot.slack.client.models.interaction.Json["view"]->
com.hubspot.slack.client.models.response.views.Json["state"]->
com.hubspot.slack.client.models.response.views.Json["task-actions:2"]->
com.hubspot.slack.client.models.response.views.Json["task.dynamicActions"])

I'm digging into a solution for this now, but I wanted to report it quickly so that others were aware. I suspect this may be affecting many users of this library today.

Allow custom rate limiters on SlackClient

Currently, SlackClient only rate limits on method, not the method-token combination that Slack actually rate limits apps on. To fix this, we'd like to be able to supply an optional RateLimiter via SlackRuntimeConfig with some well defined interface, and, if supplied, use that rate limiter in SlackClient rather than the static one (i.e. RATE_LIMITERS). Elias has also suggested we cut a release on this feature

Add test to verify method rate limit "tiers" are up to date

Problem

If the declared rate limit tier for a method is changed by Slack, we don't know our tier is out of date. If they increase the tier, we'll be throttling ourselves unnecessarily. If they reduce the tier, we'll likely to hit rate limits (essentially the in house rate limiter is useless if they reduce the tier)

Solution

We can write a test to loop through each method and check against Slack's site to verify the tier is correct. The list the tier in the Facts section for each method. eg. https://api.slack.com/methods/channels.create.

This isn't ideal, but I couldn't think of another way to verify this information except checking manually.

Add Modal support

Slack have added Modal as the replacement for dialogs.

Modals have the ability to use Block Kit interactive components, and since this library now supports Block Kit, it would be useful to add Modal support as well.

For more information on using Modals, see Reference: View payloads

  • Add POJOs for the fields specified at https://api.slack.com/reference/surfaces/views
    There should be different POJOs for Home and Modal, so that the relevant methods only get the correct amount of information.
  • add support for methods:
    • views.open
    • views.update
    • views.push
    • views.publish

Add other file types in SlackFileType

Requesting if other supported file types can be added in SlackFileType - currently only supports
these:

    TEXT("text"),
    GIF("gif"),
    CSV("csv"),
    JPG("jpg"),
    PNG("png"),
    UNKNOWN("unknown");

Please add support for these or auto or Change emu to String:


Type | Description
-- | --
auto | Auto Detect Type
text | Plain Text
ai | Illustrator File
apk | APK
applescript | AppleScript
binary | Binary
bmp | Bitmap
boxnote | BoxNote
c | C
csharp | C#
cpp | C++
css | CSS
csv | CSV
clojure | Clojure
coffeescript | CoffeeScript
cfm | ColdFusion
d | D
dart | Dart
diff | Diff
doc | Word Document
docx | Word document
dockerfile | Docker
dotx | Word template
email | Email
eps | EPS
epub | EPUB
erlang | Erlang
fla | Flash FLA
flv | Flash video
fsharp | F#
fortran | Fortran
gdoc | GDocs Document
gdraw | GDocs Drawing
gif | GIF
go | Go
gpres | GDocs Presentation
groovy | Groovy
gsheet | GDocs Spreadsheet
gzip | GZip
html | HTML
handlebars | Handlebars
haskell | Haskell
haxe | Haxe
indd | InDesign Document
java | Java
javascript | JavaScript/JSON
jpg | JPEG
keynote | Keynote Document
kotlin | Kotlin
latex | LaTeX/sTeX
lisp | Lisp
lua | Lua
m4a | MPEG 4 audio
markdown | Markdown (raw)
matlab | MATLAB
mhtml | MHTML
mkv | Matroska video
mov | QuickTime video
mp3 | mp4
mp4 | MPEG 4 video
mpg | MPEG video
mumps | MUMPS
numbers | Numbers Document
nzb | NZB
objc | Objective-C
ocaml | OCaml
odg | OpenDocument Drawing
odi | OpenDocument Image
odp | OpenDocument Presentation
ods | OpenDocument Spreadsheet
odt | OpenDocument Text
ogg | Ogg Vorbis
ogv | Ogg video
pages | Pages Document
pascal | Pascal
pdf | PDF
perl | Perl
php | PHP
pig | Pig
png | PNG
post | Slack Post
powershell | PowerShell
ppt | PowerPoint presentation
pptx | PowerPoint presentation
psd | Photoshop Document
puppet | Puppet
python | Python
qtz | Quartz Composer Composition
r | R
rtf | Rich Text File
ruby | Ruby
rust | Rust
sql | SQL
sass | Sass
scala | Scala
scheme | Scheme
sketch | Sketch File
shell | Shell
smalltalk | Smalltalk
svg | SVG
swf | Flash SWF
swift | Swift
tar | Tarball
tiff | TIFF
tsv | TSV
vb | VB.NET
vbscript | VBScript
vcard | vCard
velocity | Velocity
verilog | Verilog
wav | Waveform audio
webm | WebM
wmv | Windows Media Video
xls | Excel spreadsheet
xlsx | Excel spreadsheet
xlsb | Excel Spreadsheet (Binary, Macro Enabled)
xlsm | Excel Spreadsheet (Macro Enabled)
xltx | Excel template
xml | XML
yaml | YAML
zip | Zip

Allow team_id argument for users.list method

Is your feature request related to a problem? Please describe.

According to the Slack API docs, the users.list method requires the team_id argument when using an org-level token. The Slack App we are using is an org-level app so we are unable to use the current listUsers method in this client.

Describe the solution you'd like

We would like to request a new listUsers method which accepts the team_id as an argument.

Describe alternatives you've considered

We tried to make our app use a regular token instead of an org-level token. We discovered that once a Slack app has been set as org-level, this cannot be undone.

Create private conversation creates public channel instead

Whenever I try to create a private conversation, it creates the channel but turns it public instead.

Result<ConversationsCreateResponse, SlackError> createResult =
                slackClient.createConversation(ConversationCreateParams.builder()
                .setIsPrivate(true)
                .setName(privateChannelName)
                .build()
        ).join();

The result I also get from this is:

Create private channel: ConversationsCreateResponse{channel=SlackChannel{id=..., name=..., isArchived=false, isGeneral=false, isPrivate=false, isMember=true, channelType=CHANNEL}, ok=true, responseMetadata=ResponseMetadata{}}

Could someone please take a look? I really appreciate it, thanks!

Expected usage / lifecycle?

We recently discovered that our use of this library was leading to eventual resource starvation ("too many files"). In short, each call to SlackClientFactory.create() results in 5 additional epoll/kqueue entries in lsof. This makes sense of course, since any API client needs a pool of connections to make service calls.

The issue is that the ergonomics of the API lead you down the path of creating a SlackClient per user / access token. In some cases you'll have a single bot access token shared across all your users, but in other cases you'll have an access token per user. In the latter, you can end up with an ever-growing set of separate NingAsyncHttpClient instances. While they all share the same NioHttpClient.Factory, they appear to each create their own pool of resources.

So without calling SlackClient.close(), which isn't mentioned in the readme, you can easily end up with resource starvation.

I'd be happy to help modify the docs/readme to be clearer, but my first question is: what is the correct way to instantiate a SlackClient? Should multi-tenant services keep caches of them per user? Should we create and close one for every request that we handle? Although I've submitted a bunch of patches, I haven't looked closely at this part of the code before now. I'll keep investigating, but any feedback on proper usage lifecycle would be really helpful.

Thanks.

New release?

Last release was almost a year ago. We've been running off a fork of 0.12-SNAPSHOT, but all our contributions are merged and I'd love to depend on a regular 1.13 release :)

oauth.access

There is a chance that I just don't see it but could it be that the oauth.access endpoint is not supported?

If so, any chance we'll see this supported?

Support for non-legacy attachments

Slack's language around attachments is a bit confusing... on this page they seem to indicate that the entire concept of attachment might go away. But on this reference page they clearly define "legacy" attachment fields separate from non-legacy fields: namely color (only remaining field) and blocks.

In short: it looks like Slack wants us to to stop using all the bespoke formatting you could get in attachments and simply use Blocks, which makes sense to me.

The problem is: this projects AttachmentIF only reflects the legacy stuff (+ color) and doesn't have support for List<Block>. I tried adding List<Block> getBlocks() hoping that would be enough to get the job done, but unfortunately Slack returns with an invalid_attachments error (which, btw, isn't documented anywhere) with additional context of [ERROR] invalid_keys.

Through trial-and-error, I learned that the error happens when you include legacy fields (ex: text, mrkdwn_in, fields, etc) even if they are null. So AttachmentsIF needs a bit more work than just adding a new getter. It needs a serializer that omits all other legacy fields if blocks are provided. Or perhaps we need to further compose Attachment into LegacyAttachment and BlockAttachment.

I'll try to get a PR for this soon, but this Jackson serialization and composition stuff is slow going for me so maybe you'll get to it before I do :)

Cannot parse JSON into SlackEventWrapper for many events

This is similar to issue #52, which was resolved but seems to still be a problem for me. Specifically, I am trying to parse an incoming event action like so:

objectMapper.readValue(request.getBody(String.class).get(), SlackEventWrapper.class)

For some events, like a message, it works wonderfully. But for others, where there is no ts field, I get this error from Jackson:

Cannot construct instance of `com.hubspot.slack.client.models.events.SlackEventSkeleton`, problem: Cannot build SlackEventSkeleton, some of required attributes are not set [ts]

I would love to use all the event models that are built up in this project, as I'm already using the web API and it's working great, but this is a bit of a showstopper for me. Any ideas how to work around it?

Thank you for the great project!

New Release

There are documentation and bug fixes that address certain issues, but I don't see any new releases. When should we expect to see those released? I've downloaded version 1.0 which seems to be the only version available on the Maven repository, but that version does not include conversations.open and it still has some of the bugs that have been fixed.

Recommended way to deal with proxies?

We would like to deploy a service that sits behind an egress proxy. All https communication outside of our AWS VPC requires egress through this proxy. I do not see a documented way to set a proxy for outgoing calls to Slack.

Describe the solution you'd like

The recommended way to set a https proxy.

Describe alternatives you've considered

I went diving through the code and suspect setting properties works.

System.setProperty("http.proxyHost", host);
System.setProperty("http.proxyPort", port);

Is this the recommended way to handle proxies for the foreseeable future? Can we document that and make it part of the API?

Additional context

Happy to submit PRs back once given a +1 that properties are the best way to handle this for now.

Support for new Layout (Block Kit Builder friendly)

Is your feature request related to a problem? Please describe.
Slack released a new way of building messages. As far as I know this library does not support it yet, or am I wrong?

Describe the solution you'd like
Have a builder patter the same way we have it now with ChatPostMessageParams.builder which contemplates the new format (maybe a new type?)

Describe alternatives you've considered
Doing all the communication using a simple RestTemplate but I think this library is too good not to have the new layout. https://github.com/seratch/jslack might the option to to go

Additional context
Library now supports this: https://api.slack.com/docs/messages/builder
And should be able to support this: https://api.slack.com/tools/block-kit-builder

Date of new release

Can you tell when are you going to do new release?
Asking about version 1.5

Illegal Reflective access operation (JDK 9+)

Hi, thanks for the easy-to-use client!

The following warnings show up in JDK 9+:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.hubspot.horizon.shaded.org.jboss.netty.util.internal.ByteBufferUtil (file:/usr/share/jimage/jimage.jar) to method java.nio.DirectByteBuffer.cleaner()
WARNING: Please consider reporting this to the maintainers of com.hubspot.horizon.shaded.org.jboss.netty.util.internal.ByteBufferUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Running with --illegal-access=debug results in:

WARNING: Illegal reflective access by com.hubspot.horizon.shaded.org.jboss.netty.util.internal.ByteBufferUtil (file:/usr/share/jimage/jimage.jar) to method java.nio.DirectByteBuffer.cleaner()
	at com.hubspot.horizon.shaded.org.jboss.netty.util.internal.ByteBufferUtil.<clinit>(ByteBufferUtil.java:35)
	at com.hubspot.horizon.shaded.org.jboss.netty.channel.socket.nio.SocketReceiveBufferAllocator.newBuffer(SocketReceiveBufferAllocator.java:62)
	at com.hubspot.horizon.shaded.org.jboss.netty.channel.socket.nio.SocketReceiveBufferAllocator.get(SocketReceiveBufferAllocator.java:44)
	at com.hubspot.horizon.shaded.org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:62)
	at com.hubspot.horizon.shaded.org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:108)
	at com.hubspot.horizon.shaded.org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:337)
	at com.hubspot.horizon.shaded.org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89)
	at com.hubspot.horizon.shaded.org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	at com.hubspot.horizon.shaded.org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	at com.hubspot.horizon.shaded.org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:835)

JDK 11 and 12 should still work with warnings, but future releases will change the default runtime mode to deny.

More info here: http://openjdk.java.net/jeps/261#Relaxed-strong-encapsulation

Support multipart file uploads

#107 revealed that we don't support the full files.upload API. This looks like a relatively simple extension to what already exists. The files.upload documentation makes clear that there are two mechanisms for file upload:

  1. Via the content parameter, which is what is currently supported (and is described in the docs as recommended "...for creating a "file" from a long message/paste and forces "editable" mode.", and
  2. Via a multipart/form-data encoded file

I think we would just need to add support for the second variety (which is effectively purely additive here).

Boolean fields are not deserialized into SlackUser model

Describe the bug
We noticed that Optional<Boolean> values are not deserialized correctly into SlackUser. For example, Slack sends user with key is_bot but we expect bot due to the Jackson deserialization logic which works like that for isBot methods. We need to add get prefix to those methods to fix deserialization or specify key via @JsonProperty. The second option seems better as there are already some usages of the methods.
#180

To Reproduce
Steps to reproduce the behavior:

  1. Try to deserialize SlackUser.
  2. See that no fields with isXxx getter are deserialized.

Expected behavior
All the fields with isXxx getter are deserialized correctly.

Usage of file uploads

Hi,

I am trying to do a normal file upload but I cannot find any documentation on how to use the file upload functionality. I have tried the below but I think my problem comes in with the content of the builder:

 Result<FilesUploadResponse, SlackError> join = slackClient.uploadFile(FilesUploadParams.builder().setFilename("Test.png").setTitle("Test File").setContent("/tmp/test.png").build()).join();

Do you by any chance have an example on how to input/format the content? I have tried Base64 encoding it as well without any luck. Ideally I would like to take a byte array and upload it.

Query parameter authentication fails for new Slack apps

Much of this API client relies on passing in the token as a query parameter (?token=...). We have found that Slack has stopped supporting that method of authentication for any newly created app, though interestingly is still supporting it if the app was created at some point in the past.

For a specific example, we've seen it reliably with users.profile.get:

https://api.slack.com/methods/users.profile.get

The authentication works fine using the officially documented approach:

Tokens should be passed as an HTTP Authorization header or alternatively, as a POST parameter.

And it also works using the query parameter approach by this client for "legacy" apps, but it definitely does not work for newly created apps.

I'll also note: the API docs now indicate that users.profile.get should be a GET while this client uses POST. It wouldn't surprise me if that is related and/or will also be an issue down the road.

Error handling design can be improved

Describe the bug
The current API design uses SlackErrorIF as the error definition, which really just consists of one property error. This despite the fact that Slack server responds with a richer information.

As a result, users of this library are forced to spend unnecessary time digging into the root cause of the problem. See #153 (comment) where two users misdiagnosed the problem.

Getting developers back on track from a failure is a critical component of the library usability, and II have to say this library is currently failing that bar for me (and considering the fact that the said error, in my case, comes from the very first, simplest possible use of this library to post a hello world message!)

The current workaround is ResponseDebugger, though in my case because it didn't occur to me to install SLF4J binding, so the message was simply swallowed to void. Even if it does go to logging, its output is not correlated with the location in the program where the problem happened, nor any other contextual information that is leading up to the failed invocation.

To Reproduce
Use version 1.6 of this library, and run the PostAMessage example.

Exception in thread "main" java.lang.IllegalStateException: SlackError{type=UNKNOWN, error=invalid_arguments}
	at com.hubspot.algebra.Result.lambda$unwrapOrElseThrow$1(Result.java:68)
	at com.hubspot.algebra.Result.lambda$unwrapOrElseThrow$0(Result.java:64)
	at java.util.Optional.orElseThrow(Optional.java:290)
	at com.hubspot.algebra.Result.unwrapOrElseThrow(Result.java:60)
	at com.hubspot.algebra.Result.unwrapOrElseThrow(Result.java:64)
	at com.hubspot.algebra.Result.unwrapOrElseThrow(Result.java:68)

Expected behavior
The actual response coming from Slack API is as follows:

{"ok":false,"error":"invalid_arguments","deprecated_argument":"as_user","warning":"missing_charset","response_metadata":{"warnings":["missing_charset"]}}

So first,SlackErrorResponseIF is a better representation of a problem than SlackError.

In additiona, Slack API doesn't really specify exactly what fields are in the error response, and as a case in point in the above error, there's an otherwise undefined field name deprecated_argument. So it's futile to try to do a full databinding. A better thing to do IMO is to simply carry forward JsonNode that represents the full information of a failure.

See https://github.com/kohsuke/slack-client where I made that change.

If this is too disruptive a change of existing users of this library, please consider allowing SlackErrorIF to point back to the parent SlackErrorResponseIF, so that the information can be retained in a much more compatible manner.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.