summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorChris <ccbrown112@gmail.com>2017-08-29 16:14:59 -0500
committerGitHub <noreply@github.com>2017-08-29 16:14:59 -0500
commit213a072b38d29d3c3ec8e150584685b1144a7d6a (patch)
tree1da10a494e49914b0f6641db79e7dcf8ad3886f6 /app
parent59798c137584a0b7e008ec713b489929dd83a690 (diff)
downloadchat-213a072b38d29d3c3ec8e150584685b1144a7d6a.tar.gz
chat-213a072b38d29d3c3ec8e150584685b1144a7d6a.tar.bz2
chat-213a072b38d29d3c3ec8e150584685b1144a7d6a.zip
PLT-6403: Interactive messages (#7274)
* wip * finish first pass * requested changes * add DoPostAction to Client4
Diffstat (limited to 'app')
-rw-r--r--app/command.go2
-rw-r--r--app/notification.go4
-rw-r--r--app/post.go67
-rw-r--r--app/post_test.go72
4 files changed, 138 insertions, 7 deletions
diff --git a/app/command.go b/app/command.go
index b9d6748fb..a2e63a3d4 100644
--- a/app/command.go
+++ b/app/command.go
@@ -53,7 +53,7 @@ func CreateCommandPost(post *model.Post, teamId string, response *model.CommandR
}
post.ParentId = ""
- SendEphemeralPost(teamId, post.UserId, post)
+ SendEphemeralPost(post.UserId, post)
}
return post, nil
diff --git a/app/notification.go b/app/notification.go
index 258606ad4..af7589934 100644
--- a/app/notification.go
+++ b/app/notification.go
@@ -182,7 +182,6 @@ func SendNotifications(post *model.Post, team *model.Team, channel *model.Channe
if hereNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
hereNotification = false
SendEphemeralPost(
- team.Id,
post.UserId,
&model.Post{
ChannelId: post.ChannelId,
@@ -195,7 +194,6 @@ func SendNotifications(post *model.Post, team *model.Team, channel *model.Channe
// If the channel has more than 1K users then @channel is disabled
if channelNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
SendEphemeralPost(
- team.Id,
post.UserId,
&model.Post{
ChannelId: post.ChannelId,
@@ -208,7 +206,6 @@ func SendNotifications(post *model.Post, team *model.Team, channel *model.Channe
// If the channel has more than 1K users then @all is disabled
if allNotification && int64(len(profileMap)) > *utils.Cfg.TeamSettings.MaxNotificationsPerChannel {
SendEphemeralPost(
- team.Id,
post.UserId,
&model.Post{
ChannelId: post.ChannelId,
@@ -734,7 +731,6 @@ func sendOutOfChannelMentions(sender *model.User, post *model.Post, teamId strin
}
SendEphemeralPost(
- teamId,
post.UserId,
&model.Post{
ChannelId: post.ChannelId,
diff --git a/app/post.go b/app/post.go
index 5b83ab7a2..c852a90d2 100644
--- a/app/post.go
+++ b/app/post.go
@@ -4,8 +4,11 @@
package app
import (
+ "encoding/json"
+ "fmt"
"net/http"
"regexp"
+ "strings"
l4g "github.com/alecthomas/log4go"
"github.com/dyatlov/go-opengraph/opengraph"
@@ -210,7 +213,7 @@ func parseSlackLinksToMarkdown(text string) string {
return linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})")
}
-func SendEphemeralPost(teamId, userId string, post *model.Post) *model.Post {
+func SendEphemeralPost(userId string, post *model.Post) *model.Post {
post.Type = model.POST_EPHEMERAL
// fill in fields which haven't been specified which have sensible defaults
@@ -638,3 +641,65 @@ func GetOpenGraphMetadata(url string) *opengraph.OpenGraph {
return og
}
+
+func DoPostAction(postId string, actionId string, userId string) *model.AppError {
+ pchan := Srv.Store.Post().GetSingle(postId)
+
+ var post *model.Post
+ if result := <-pchan; result.Err != nil {
+ return result.Err
+ } else {
+ post = result.Data.(*model.Post)
+ }
+
+ action := post.GetAction(actionId)
+ if action == nil || action.Integration == nil {
+ return model.NewAppError("DoPostAction", "api.post.do_action.action_id.app_error", nil, fmt.Sprintf("action=%v", action), http.StatusNotFound)
+ }
+
+ request := &model.PostActionIntegrationRequest{
+ UserId: userId,
+ Context: action.Integration.Context,
+ }
+
+ req, _ := http.NewRequest("POST", action.Integration.URL, strings.NewReader(request.ToJson()))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Accept", "application/json")
+ resp, err := utils.HttpClient(false).Do(req)
+ if err != nil {
+ return model.NewAppError("DoPostAction", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return model.NewAppError("DoPostAction", "api.post.do_action.action_integration.app_error", nil, fmt.Sprintf("status=%v", resp.StatusCode), http.StatusBadRequest)
+ }
+
+ var response model.PostActionIntegrationResponse
+ if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
+ return model.NewAppError("DoPostAction", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
+ }
+
+ if response.Update != nil {
+ response.Update.Id = postId
+ response.Update.AddProp("from_webhook", "true")
+ if _, err := UpdatePost(response.Update, false); err != nil {
+ return err
+ }
+ }
+
+ if response.EphemeralText != "" {
+ ephemeralPost := &model.Post{}
+ ephemeralPost.Message = parseSlackLinksToMarkdown(response.EphemeralText)
+ ephemeralPost.ChannelId = post.ChannelId
+ ephemeralPost.RootId = post.RootId
+ if ephemeralPost.RootId == "" {
+ ephemeralPost.RootId = post.Id
+ }
+ ephemeralPost.UserId = userId
+ ephemeralPost.AddProp("from_webhook", "true")
+ SendEphemeralPost(userId, ephemeralPost)
+ }
+
+ return nil
+}
diff --git a/app/post_test.go b/app/post_test.go
index 416fbfc9e..ab8e27021 100644
--- a/app/post_test.go
+++ b/app/post_test.go
@@ -4,11 +4,18 @@
package app
import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
"testing"
"time"
- "fmt"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
)
func TestUpdatePostEditAt(t *testing.T) {
@@ -68,3 +75,66 @@ func TestPostReplyToPostWhereRootPosterLeftChannel(t *testing.T) {
t.Fatal(err)
}
}
+
+func TestPostAction(t *testing.T) {
+ th := Setup().InitBasic()
+
+ allowedInternalConnections := *utils.Cfg.ServiceSettings.AllowedUntrustedInternalConnections
+ defer func() {
+ utils.Cfg.ServiceSettings.AllowedUntrustedInternalConnections = &allowedInternalConnections
+ }()
+ *utils.Cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1"
+
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ var request model.PostActionIntegrationRequest
+ err := json.NewDecoder(r.Body).Decode(&request)
+ assert.NoError(t, err)
+ assert.Equal(t, request.UserId, th.BasicUser.Id)
+ assert.Equal(t, "foo", request.Context["s"])
+ assert.EqualValues(t, 3, request.Context["n"])
+ fmt.Fprintf(w, `{"update": {"message": "updated"}, "ephemeral_text": "foo"}`)
+ }))
+ defer ts.Close()
+
+ interactivePost := model.Post{
+ Message: "Interactive post",
+ ChannelId: th.BasicChannel.Id,
+ PendingPostId: model.NewId() + ":" + fmt.Sprint(model.GetMillis()),
+ UserId: th.BasicUser.Id,
+ Props: model.StringInterface{
+ "attachments": []*model.SlackAttachment{
+ &model.SlackAttachment{
+ Text: "hello",
+ Actions: []*model.PostAction{
+ &model.PostAction{
+ Integration: &model.PostActionIntegration{
+ Context: model.StringInterface{
+ "s": "foo",
+ "n": 3,
+ },
+ URL: ts.URL,
+ },
+ Name: "action",
+ },
+ },
+ },
+ },
+ },
+ }
+
+ post, err := CreatePostAsUser(&interactivePost)
+ require.Nil(t, err)
+
+ attachments, ok := post.Props["attachments"].([]*model.SlackAttachment)
+ require.True(t, ok)
+
+ require.NotEmpty(t, attachments[0].Actions)
+ require.NotEmpty(t, attachments[0].Actions[0].Id)
+
+ err = DoPostAction(post.Id, "notavalidid", th.BasicUser.Id)
+ require.NotNil(t, err)
+ assert.Equal(t, http.StatusNotFound, err.StatusCode)
+
+ err = DoPostAction(post.Id, attachments[0].Actions[0].Id, th.BasicUser.Id)
+ require.Nil(t, err)
+}