Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[experimental] introduction of Slack workflow steps #1027

Merged
merged 35 commits into from Mar 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
636f906
introduce workflow step app functionality
Jan 30, 2022
b5814ae
tests for workflowStep added
Feb 2, 2022
b13d00e
example workflowStep app added
Feb 2, 2022
7f4937f
readme improved
Feb 4, 2022
4631577
unused variable in example removed, switch line indention to tabulator
Feb 4, 2022
0a59db7
using snake case for new directory and file
Feb 8, 2022
4d6e826
Add refresh_token and token_type to OAuthV2Response fields
Feb 10, 2022
9cad061
Merge pull request #1030 from hidenami-i/master
kanata2 Feb 12, 2022
7f6b224
all: add new //go:build lines
zchee Feb 13, 2022
eaf6740
all: remove github.com/pkg/errors dependency
zchee Feb 13, 2022
1bc0bcc
Merge pull request #1032 from zchee/go117-buildtag
kanata2 Feb 13, 2022
86cef73
vendor: run go mod vendor
zchee Feb 13, 2022
bbab81d
Merge pull request #1033 from zchee/remove-pkg-errors-deps
kanata2 Feb 13, 2022
c01cb38
messageID: add benchmark for NewSafeID
zchee Feb 14, 2022
fb30ed3
messageID: optimize NewSafeID using atomic instead of mutex lock
zchee Feb 14, 2022
1265b2e
messageID: add NewSafeID testcase
zchee Feb 14, 2022
af5cf8b
switch go code style for imports from gofmt to goimports
Feb 14, 2022
0389f44
all: support pass context.Context to all methods
zchee Feb 14, 2022
dacbdf8
webhooks: remove go1.12 support
zchee Feb 14, 2022
d89251b
misc: use NewRequestWithContext
zchee Feb 14, 2022
1645ac2
misc: use http.MethodXXX constant
zchee Feb 14, 2022
daa4329
messageID: fix atomic operation suggested by brainexe
zchee Feb 24, 2022
93ff3fb
messageID: add documentation
zchee Feb 24, 2022
67b468f
chat: add some BuildRequestContext methods for backwards compatibility
zchee Feb 24, 2022
741a1f5
webhook: remove unnecessary PostWebhookContextCustomHTTP function
zchee Feb 24, 2022
ff619ea
Merge pull request #1034 from zchee/ctx-aware
zchee Feb 24, 2022
f6658aa
Merge pull request #1035 from zchee/opt-new-safe-id
zchee Feb 24, 2022
486fde5
introduce workflow step app functionality
Jan 30, 2022
b57471c
tests for workflowStep added
Feb 2, 2022
fabe21a
example workflowStep app added
Feb 2, 2022
dd80d02
readme improved
Feb 4, 2022
81b0160
unused variable in example removed, switch line indention to tabulator
Feb 4, 2022
cd34138
using snake case for new directory and file
Feb 8, 2022
c90fe4e
switch go code style for imports from gofmt to goimports
Feb 14, 2022
b5149b1
rebase
Feb 28, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion apps.go
Expand Up @@ -44,14 +44,18 @@ func (api *Client) ListEventAuthorizationsContext(ctx context.Context, eventCont
}

func (api *Client) UninstallApp(clientID, clientSecret string) error {
return api.UninstallAppContext(context.Background(), clientID, clientSecret)
}

func (api *Client) UninstallAppContext(ctx context.Context, clientID, clientSecret string) error {
values := url.Values{
"client_id": {clientID},
"client_secret": {clientSecret},
}

response := SlackResponse{}

err := api.getMethod(context.Background(), "apps.uninstall", api.token, values, &response)
err := api.getMethod(ctx, "apps.uninstall", api.token, values, &response)
if err != nil {
return err
}
Expand Down
3 changes: 1 addition & 2 deletions block_conv.go
Expand Up @@ -2,9 +2,8 @@ package slack

import (
"encoding/json"
"errors"
"fmt"

"github.com/pkg/errors"
)

type sumtype struct {
Expand Down
60 changes: 29 additions & 31 deletions chat.go
Expand Up @@ -86,12 +86,7 @@ func NewPostMessageParameters() PostMessageParameters {

// DeleteMessage deletes a message in a channel
func (api *Client) DeleteMessage(channel, messageTimestamp string) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(
context.Background(),
channel,
MsgOptionDelete(messageTimestamp),
)
return respChannel, respTimestamp, err
return api.DeleteMessageContext(context.Background(), channel, messageTimestamp)
}

// DeleteMessageContext deletes a message in a channel with a custom context
Expand All @@ -108,8 +103,15 @@ func (api *Client) DeleteMessageContext(ctx context.Context, channel, messageTim
// Message is escaped by default according to https://api.slack.com/docs/formatting
// Use http://davestevens.github.io/slack-message-builder/ to help crafting your message.
func (api *Client) ScheduleMessage(channelID, postAt string, options ...MsgOption) (string, string, error) {
return api.ScheduleMessageContext(context.Background(), channelID, postAt, options...)
}

// ScheduleMessageContext sends a message to a channel with a custom context
//
// For more details, see ScheduleMessage documentation.
func (api *Client) ScheduleMessageContext(ctx context.Context, channelID, postAt string, options ...MsgOption) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(
context.Background(),
ctx,
channelID,
MsgOptionSchedule(postAt),
MsgOptionCompose(options...),
Expand All @@ -121,13 +123,7 @@ func (api *Client) ScheduleMessage(channelID, postAt string, options ...MsgOptio
// Message is escaped by default according to https://api.slack.com/docs/formatting
// Use http://davestevens.github.io/slack-message-builder/ to help crafting your message.
func (api *Client) PostMessage(channelID string, options ...MsgOption) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(
context.Background(),
channelID,
MsgOptionPost(),
MsgOptionCompose(options...),
)
return respChannel, respTimestamp, err
return api.PostMessageContext(context.Background(), channelID, options...)
}

// PostMessageContext sends a message to a channel with a custom context
Expand All @@ -146,12 +142,7 @@ func (api *Client) PostMessageContext(ctx context.Context, channelID string, opt
// Message is escaped by default according to https://api.slack.com/docs/formatting
// Use http://davestevens.github.io/slack-message-builder/ to help crafting your message.
func (api *Client) PostEphemeral(channelID, userID string, options ...MsgOption) (string, error) {
return api.PostEphemeralContext(
context.Background(),
channelID,
userID,
options...,
)
return api.PostEphemeralContext(context.Background(), channelID, userID, options...)
}

// PostEphemeralContext sends an ephemeal message to a user in a channel with a custom context
Expand All @@ -168,12 +159,7 @@ func (api *Client) PostEphemeralContext(ctx context.Context, channelID, userID s

// UpdateMessage updates a message in a channel
func (api *Client) UpdateMessage(channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
return api.SendMessageContext(
context.Background(),
channelID,
MsgOptionUpdate(timestamp),
MsgOptionCompose(options...),
)
return api.UpdateMessageContext(context.Background(), channelID, timestamp, options...)
}

// UpdateMessageContext updates a message in a channel
Expand Down Expand Up @@ -225,7 +211,7 @@ func (api *Client) SendMessageContext(ctx context.Context, channelID string, opt
response chatResponseFull
)

if req, parser, err = buildSender(api.endpoint, options...).BuildRequest(api.token, channelID); err != nil {
if req, parser, err = buildSender(api.endpoint, options...).BuildRequestContext(ctx, api.token, channelID); err != nil {
return "", "", "", err
}

Expand Down Expand Up @@ -306,6 +292,10 @@ type sendConfig struct {
}

func (t sendConfig) BuildRequest(token, channelID string) (req *http.Request, _ func(*chatResponseFull) responseParser, err error) {
return t.BuildRequestContext(context.Background(), token, channelID)
}

func (t sendConfig) BuildRequestContext(ctx context.Context, token, channelID string) (req *http.Request, _ func(*chatResponseFull) responseParser, err error) {
if t, err = applyMsgOptions(token, channelID, t.apiurl, t.options...); err != nil {
return nil, nil, err
}
Expand All @@ -320,9 +310,9 @@ func (t sendConfig) BuildRequest(token, channelID string) (req *http.Request, _
responseType: t.responseType,
replaceOriginal: t.replaceOriginal,
deleteOriginal: t.deleteOriginal,
}.BuildRequest()
}.BuildRequestContext(ctx)
default:
return formSender{endpoint: t.endpoint, values: t.values}.BuildRequest()
return formSender{endpoint: t.endpoint, values: t.values}.BuildRequestContext(ctx)
}
}

Expand All @@ -332,7 +322,11 @@ type formSender struct {
}

func (t formSender) BuildRequest() (*http.Request, func(*chatResponseFull) responseParser, error) {
req, err := formReq(t.endpoint, t.values)
return t.BuildRequestContext(context.Background())
}

func (t formSender) BuildRequestContext(ctx context.Context) (*http.Request, func(*chatResponseFull) responseParser, error) {
req, err := formReq(ctx, t.endpoint, t.values)
return req, func(resp *chatResponseFull) responseParser {
return newJSONParser(resp)
}, err
Expand All @@ -349,7 +343,11 @@ type responseURLSender struct {
}

func (t responseURLSender) BuildRequest() (*http.Request, func(*chatResponseFull) responseParser, error) {
req, err := jsonReq(t.endpoint, Msg{
return t.BuildRequestContext(context.Background())
}

func (t responseURLSender) BuildRequestContext(ctx context.Context) (*http.Request, func(*chatResponseFull) responseParser, error) {
req, err := jsonReq(ctx, t.endpoint, Msg{
Text: t.values.Get("text"),
Timestamp: t.values.Get("ts"),
Attachments: t.attachments,
Expand Down
59 changes: 59 additions & 0 deletions examples/workflow_step/README.md
@@ -0,0 +1,59 @@
#WorkflowStep

Have you ever wanted to run an app from a Slack workflow? This sample app shows you how it works.

Slack describes some of the basics here:
https://api.slack.com/workflows/steps
https://api.slack.com/tutorials/workflow-builder-steps


1. Start the example app localy on port 8080


2. Use ngrok to expose your app to the internet

```shell
./ngrok http 8080
```
Copy the https forwarding URL and paste it into the app manifest down below (event_subscription request_url and interactivity request_url)


3. Create a new Slack App at api.slack.com/apps from an app manifest

The manifest of a sample Slack App looks like this:
```yaml
display_information:
name: Workflowstep-Example
features:
bot_user:
display_name: Workflowstep-Example
always_online: false
workflow_steps:
- name: Example Step
callback_id: example-step
oauth_config:
scopes:
bot:
- workflow.steps:execute
settings:
event_subscriptions:
request_url: https://*****.ngrok.io/api/v1/example-step
bot_events:
- workflow_step_execute
interactivity:
is_enabled: true
request_url: https://*****.ngrok.io/api/v1/interaction
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false
```

("Interactivity" and "Enable Events" should be turned on)

4. Slack Workflow (**paid plan required!**)
1. Create a new Workflow at app.slack.com/workflow-builder
2. give it a name
3. select "Planned date & time"
4. add another step and select "Example Step" from App Workflowstep-Example
5. configure your app and hit save
6. don't forget to publish your workflow
9 changes: 9 additions & 0 deletions examples/workflow_step/go.mod
@@ -0,0 +1,9 @@
module workflowstep-example

go 1.17

require (
github.com/gorilla/websocket v1.4.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/slack-go/slack v0.10.1 // indirect
)
11 changes: 11 additions & 0 deletions examples/workflow_step/go.sum
@@ -0,0 +1,11 @@
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/slack-go/slack v0.10.1 h1:BGbxa0kMsGEvLOEoZmYs8T1wWfoZXwmQFBb6FgYCXUA=
github.com/slack-go/slack v0.10.1/go.mod h1:wWL//kk0ho+FcQXcBTmEafUI5dz4qz5f4mMk8oIkioQ=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=