slackapi / java-slack-sdk

Slack Developer Kit (including Bolt for Java) for any JVM language
https://slack.dev/java-slack-sdk/
MIT License
570 stars 209 forks source link

Add custom function support #1241

Closed seratch closed 1 week ago

seratch commented 9 months ago

This pull request adds remote function support, which is still in beta, to this SDK. Sorry, the duplicated PRs (due to my operation error) are confusing but this is the final version of https://github.com/slackapi/java-slack-sdk/pull/1239

Developers can implement a remote function and its interactivity this way:

// app.event(FunctionExecutedEvent.class, (req, ctx) -> {
// app.function("hello", (req, ctx) -> {
app.function(Pattern.compile("^he.+$"), (req, ctx) -> {
  ctx.logger.info("req: {}", req);
  ctx.client().chatPostMessage(r -> r
    .channel(req.getEvent().getInputs().get("user_id").asString())
    .text("hey!")
    .blocks(asBlocks(actions(a -> a.blockId("b").elements(asElements(
      button(b -> b.actionId("remote-function-button-success").value("clicked").text(plainText("block_actions success"))),
      button(b -> b.actionId("remote-function-button-error").value("clicked").text(plainText("block_actions error"))),
      button(b -> b.actionId("remote-function-modal").value("clicked").text(plainText("modal view")))
    )))))
  );
  return ctx.ack();
});

app.blockAction("remote-function-button-success", (req, ctx) -> {
  Map<String, Object> outputs = new HashMap<>();
  outputs.put("user_id", req.getPayload().getFunctionData().getInputs().get("user_id").asString());
  ctx.client().functionsCompleteSuccess(r -> r
    .functionExecutionId(req.getPayload().getFunctionData().getExecutionId())
    .outputs(outputs)
  );
  ctx.client().chatUpdate(r -> r
    .channel(req.getPayload().getContainer().getChannelId())
    .ts(req.getPayload().getContainer().getMessageTs())
    .text("Thank you!")
  );
  return ctx.ack();
});
app.blockAction("remote-function-button-error", (req, ctx) -> {
  ctx.client().functionsCompleteError(r -> r
    .functionExecutionId(req.getPayload().getFunctionData().getExecutionId())
    .error("test error!")
  );
  ctx.client().chatUpdate(r -> r
    .channel(req.getPayload().getContainer().getChannelId())
    .ts(req.getPayload().getContainer().getMessageTs())
    .text("Thank you!")
  );
  return ctx.ack();
});
app.blockAction("remote-function-modal", (req, ctx) -> {
  ctx.client().viewsOpen(r -> r
    .triggerId(req.getPayload().getInteractivity().getInteractivityPointer())
    .view(view(v -> v
      .type("modal")
      .callbackId("remote-function-view")
      .title(viewTitle(vt -> vt.type("plain_text").text("Remote Function test")))
      .close(viewClose(vc -> vc.type("plain_text").text("Close")))
      .submit(viewSubmit(vs -> vs.type("plain_text").text("Submit")))
      .notifyOnClose(true)
      .blocks(asBlocks(input(input -> input
        .blockId("text-block")
        .element(plainTextInput(pti -> pti.actionId("text-action").multiline(true)))
        .label(plainText(pt -> pt.text("Text").emoji(true)))
      )))
    )));
  ctx.client().chatUpdate(r -> r
    .channel(req.getPayload().getContainer().getChannelId())
    .ts(req.getPayload().getContainer().getMessageTs())
    .text("Thank you!")
  );
  return ctx.ack();
});

app.viewSubmission("remote-function-view", (req, ctx) -> {
  Map<String, Object> outputs = new HashMap<>();
  outputs.put("user_id", ctx.getRequestUserId());
  ctx.client().functionsCompleteSuccess(r -> r
    .functionExecutionId(req.getPayload().getFunctionData().getExecutionId())
    .outputs(outputs)
  );
  return ctx.ack();
});
app.viewClosed("remote-function-view", (req, ctx) -> {
  Map<String, Object> outputs = new HashMap<>();
  outputs.put("user_id", ctx.getRequestUserId());
  ctx.client().functionsCompleteSuccess(r -> r
    .functionExecutionId(req.getPayload().getFunctionData().getExecutionId())
    .outputs(outputs)
  );
  return ctx.ack();
});

References:

Category (place an x in each of the [ ])

Requirements

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you agree to those rules.

codecov[bot] commented 9 months ago

Codecov Report

Attention: Patch coverage is 71.73913% with 13 lines in your changes missing coverage. Please review.

Project coverage is 74.96%. Comparing base (efa3f24) to head (9dd4118). Report is 1 commits behind head on main.

Files Patch % Lines
bolt/src/main/java/com/slack/api/bolt/App.java 57.14% 2 Missing and 4 partials :warning:
...m/slack/api/bolt/request/builtin/EventRequest.java 57.14% 0 Missing and 3 partials :warning:
...ck/api/bolt/request/builtin/ViewClosedRequest.java 33.33% 1 Missing and 1 partial :warning:
.../main/java/com/slack/api/bolt/context/Context.java 83.33% 0 Missing and 1 partial :warning:
...k/api/bolt/request/builtin/BlockActionRequest.java 85.71% 0 Missing and 1 partial :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #1241 +/- ## ============================================ - Coverage 74.99% 74.96% -0.03% - Complexity 4190 4202 +12 ============================================ Files 452 453 +1 Lines 12931 12975 +44 Branches 1331 1342 +11 ============================================ + Hits 9697 9727 +30 - Misses 2463 2467 +4 - Partials 771 781 +10 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.