summaryrefslogtreecommitdiffstats
path: root/app/webhook.go
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-01-13 13:53:37 -0500
committerGitHub <noreply@github.com>2017-01-13 13:53:37 -0500
commit97558f6a6ec4c53fa69035fb430ead209d9c222d (patch)
tree6fc57f5b75b15a025348c6e295cea6aedb9e69ae /app/webhook.go
parent07bad4d6d518a9012a20fec8309cd625f57c7a8c (diff)
downloadchat-97558f6a6ec4c53fa69035fb430ead209d9c222d.tar.gz
chat-97558f6a6ec4c53fa69035fb430ead209d9c222d.tar.bz2
chat-97558f6a6ec4c53fa69035fb430ead209d9c222d.zip
PLT-4938 Add app package and move logic over from api package (#4931)
* Add app package and move logic over from api package * Change app package functions to return errors * Move non-api tests into app package * Fix merge
Diffstat (limited to 'app/webhook.go')
-rw-r--r--app/webhook.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/app/webhook.go b/app/webhook.go
new file mode 100644
index 000000000..dfd59349f
--- /dev/null
+++ b/app/webhook.go
@@ -0,0 +1,155 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "crypto/tls"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strings"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+const (
+ TRIGGERWORDS_FULL = 0
+ TRIGGERWORDS_STARTSWITH = 1
+)
+
+func handleWebhookEvents(post *model.Post, team *model.Team, channel *model.Channel, user *model.User) *model.AppError {
+ if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
+ return nil
+ }
+
+ if channel.Type != model.CHANNEL_OPEN {
+ return nil
+ }
+
+ hchan := Srv.Store.Webhook().GetOutgoingByTeam(team.Id)
+ result := <-hchan
+ if result.Err != nil {
+ return result.Err
+ }
+
+ hooks := result.Data.([]*model.OutgoingWebhook)
+ if len(hooks) == 0 {
+ return nil
+ }
+
+ splitWords := strings.Fields(post.Message)
+ if len(splitWords) == 0 {
+ return nil
+ }
+ firstWord := splitWords[0]
+
+ relevantHooks := []*model.OutgoingWebhook{}
+ for _, hook := range hooks {
+ if hook.ChannelId == post.ChannelId || len(hook.ChannelId) == 0 {
+ if hook.ChannelId == post.ChannelId && len(hook.TriggerWords) == 0 {
+ relevantHooks = append(relevantHooks, hook)
+ } else if hook.TriggerWhen == TRIGGERWORDS_FULL && hook.HasTriggerWord(firstWord) {
+ relevantHooks = append(relevantHooks, hook)
+ } else if hook.TriggerWhen == TRIGGERWORDS_STARTSWITH && hook.TriggerWordStartsWith(firstWord) {
+ relevantHooks = append(relevantHooks, hook)
+ }
+ }
+ }
+
+ for _, hook := range relevantHooks {
+ go func(hook *model.OutgoingWebhook) {
+ payload := &model.OutgoingWebhookPayload{
+ Token: hook.Token,
+ TeamId: hook.TeamId,
+ TeamDomain: team.Name,
+ ChannelId: post.ChannelId,
+ ChannelName: channel.Name,
+ Timestamp: post.CreateAt,
+ UserId: post.UserId,
+ UserName: user.Username,
+ PostId: post.Id,
+ Text: post.Message,
+ TriggerWord: firstWord,
+ }
+ var body io.Reader
+ var contentType string
+ if hook.ContentType == "application/json" {
+ body = strings.NewReader(payload.ToJSON())
+ contentType = "application/json"
+ } else {
+ body = strings.NewReader(payload.ToFormValues())
+ contentType = "application/x-www-form-urlencoded"
+ }
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ client := &http.Client{Transport: tr}
+
+ for _, url := range hook.CallbackURLs {
+ go func(url string) {
+ req, _ := http.NewRequest("POST", url, body)
+ req.Header.Set("Content-Type", contentType)
+ req.Header.Set("Accept", "application/json")
+ if resp, err := client.Do(req); err != nil {
+ l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.event_post.error"), err.Error())
+ } else {
+ defer func() {
+ ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ }()
+ respProps := model.MapFromJson(resp.Body)
+
+ if text, ok := respProps["text"]; ok {
+ if _, err := CreateWebhookPost(hook.CreatorId, hook.TeamId, post.ChannelId, text, respProps["username"], respProps["icon_url"], post.Props, post.Type); err != nil {
+ l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.create_post.error"), err)
+ }
+ }
+ }
+ }(url)
+ }
+
+ }(hook)
+ }
+
+ return nil
+}
+
+func CreateWebhookPost(userId, teamId, channelId, text, overrideUsername, overrideIconUrl string, props model.StringInterface, postType string) (*model.Post, *model.AppError) {
+ post := &model.Post{UserId: userId, ChannelId: channelId, Message: text, Type: postType}
+ post.AddProp("from_webhook", "true")
+
+ if utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
+ if len(overrideUsername) != 0 {
+ post.AddProp("override_username", overrideUsername)
+ } else {
+ post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
+ }
+ }
+
+ if utils.Cfg.ServiceSettings.EnablePostIconOverride {
+ if len(overrideIconUrl) != 0 {
+ post.AddProp("override_icon_url", overrideIconUrl)
+ }
+ }
+
+ post.Message = parseSlackLinksToMarkdown(post.Message)
+
+ if len(props) > 0 {
+ for key, val := range props {
+ if key == "attachments" {
+ parseSlackAttachment(post, val)
+ } else if key != "override_icon_url" && key != "override_username" && key != "from_webhook" {
+ post.AddProp(key, val)
+ }
+ }
+ }
+
+ if _, err := CreatePost(post, teamId, false); err != nil {
+ return nil, model.NewLocAppError("CreateWebhookPost", "api.post.create_webhook_post.creating.app_error", nil, "err="+err.Message)
+ }
+
+ return post, nil
+}