Reputation: 14185
Here is my golang app listening requests from slack command:
main.go
:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
type SlackCmdResponse struct {
Text string `json:"text"`
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
if err := req.ParseForm(); err != nil {
panic(err)
}
responseUrl := req.PostFormValue("response_url")
go func() {
time.Sleep(time.Second)
postBack(responseUrl)
}()
rj, err := json.Marshal(SlackCmdResponse{Text: "Test started"})
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(rj)
})
fmt.Println("listening 8383")
if err := http.ListenAndServe(":8383", nil); err != nil {
panic(err)
}
}
func postBack(responseUrl string) {
fmt.Println("responseUrl", responseUrl)
cResp := SlackCmdResponse{
Text: "Test finished",
}
cj, err := json.Marshal(cResp)
if err != nil {
panic(err)
}
req, err := http.NewRequest("POST", responseUrl, bytes.NewReader(cj))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
if resp != nil {
fmt.Println(resp.StatusCode)
if b, err := ioutil.ReadAll(resp.Body); err != nil {
panic(err)
} else {
fmt.Println(string(b))
}
if resp.Body != nil {
resp.Body.Close()
}
}
}
I run it:
$ go run main.go
listening 8383
I use ngrok to make it accessible from the internet:
ngrok http 8383
I created slack slash command /my-command
with POST
option and pasted https URL that ngrok gave:
Now when I run /my-command
in slack, I get slack reply Test started
. And then in a second slack prints Test finished
For now, it's all fine.
If I replace line
time.Sleep(time.Second)
by line
time.Sleep(time.Hour) // long test
I don't get slack printed "Test finished" in hour. Instead, I see in my app logs:
responseUrl https://hooks.slack.com/commands/T3GBFUZ64/86817661808/XRmDO21jYaP1Wzu7GFpNw9eW
404
Expired url
Looks like slack's response URL has an expiration time. How to extend this expiration time?
Or in a case of expiration, is there another way to send a message to the user about having the test finished? I have name and id of a user launching /my-command
req.PostFormValue("user_name")
req.PostFormValue("user_id")
So I want to run integration tests by slack which are longer than 2 hours and get a response after finishing such tests in slack.
Upvotes: 4
Views: 2001
Reputation: 4724
You can not increase the expire time for the URL that is a Slack internal setting.
You can send unattended messages to any user through the Slack Web API which you need a token for it.
For more information check: https://api.slack.com/web.
The Slack API has a postMessage
command that allows the user to post messages to a channel, to the slackbot
channel and to the user through IM
channel (direct message). It seems you want to do the later which is quite simple.
Method Url: https://slack.com/api/chat.postMessage
Posting to an IM channel is a little more complex when settings the value of channel
depending on the value of as_user
.
as_user
is false:
@chris
) as the value of channel
to post to that user's @slackbot channel as the bot.D023BB3L2
) as the value of channel
to post to that IM channel as the bot. The IM channel's ID can be retrieved through the im.list API method.as_user
is true:
D023BB3L2
) as the value of channel
to post to that IM channel as the authenticated user. The IM channel's ID can be retrieved through the im.list API method.
To send a direct message to the user owning the token used in the request, provide the channel field with the a conversation/IM ID value found in a method like im.list.To send a direct message to the user owning the token used in the request, provide the channel
field with the a conversation/IM ID value found in a method like im.list.
This method will return a list of direct messages channels if you don't have a channel open with the user yet you can call the im.open
.
This method is used to open
a direct message channel
with a specified user.
Documentation about im.open
can be found here.
https://slack.com/api/chat.postMessage?token=**TOKEN**&channel=**Direct Channel ID**&text=HelloWorld&as_user=true&pretty=1
Just replace **TOKEN**
and **Direct Channel ID**
with your values and it should send a direct message to the specified user.
Upvotes: 4