diff --git a/api/post.go b/api/post.go index 9bf6cff40f..c363ff0769 100644 --- a/api/post.go +++ b/api/post.go @@ -25,6 +25,11 @@ import ( "github.com/mattermost/platform/utils" ) +const ( + TRIGGERWORDS_FULL = 0 + TRIGGERWORDS_STARTSWITH = 1 +) + func InitPost() { l4g.Debug(utils.T("api.post.init.debug")) @@ -383,12 +388,14 @@ func handleWebhookEvents(c *Context, post *model.Post, team *model.Team, channel relevantHooks := []*model.OutgoingWebhook{} for _, hook := range hooks { - if hook.ChannelId == post.ChannelId { - if len(hook.TriggerWords) == 0 || hook.HasTriggerWord(firstWord) { + 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) } - } else if len(hook.ChannelId) == 0 && hook.HasTriggerWord(firstWord) { - relevantHooks = append(relevantHooks, hook) } } diff --git a/model/outgoing_webhook.go b/model/outgoing_webhook.go index ee7a32f1f6..ec2ed75c78 100644 --- a/model/outgoing_webhook.go +++ b/model/outgoing_webhook.go @@ -9,6 +9,7 @@ import ( "io" "net/url" "strconv" + "strings" ) type OutgoingWebhook struct { @@ -21,6 +22,7 @@ type OutgoingWebhook struct { ChannelId string `json:"channel_id"` TeamId string `json:"team_id"` TriggerWords StringArray `json:"trigger_words"` + TriggerWhen int `json:"trigger_when"` CallbackURLs StringArray `json:"callback_urls"` DisplayName string `json:"display_name"` Description string `json:"description"` @@ -171,6 +173,10 @@ func (o *OutgoingWebhook) IsValid() *AppError { return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "") } + if o.TriggerWhen > 1 { + return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "") + } + return nil } @@ -204,3 +210,17 @@ func (o *OutgoingWebhook) HasTriggerWord(word string) bool { return false } + +func (o *OutgoingWebhook) TriggerWordStartsWith(word string) bool { + if len(o.TriggerWords) == 0 || len(word) == 0 { + return false + } + + for _, trigger := range o.TriggerWords { + if strings.HasPrefix(word, trigger) { + return true + } + } + + return false +} diff --git a/model/outgoing_webhook_test.go b/model/outgoing_webhook_test.go index 24b81d2218..2458c62e41 100644 --- a/model/outgoing_webhook_test.go +++ b/model/outgoing_webhook_test.go @@ -163,3 +163,14 @@ func TestOutgoingWebhookPreUpdate(t *testing.T) { o := OutgoingWebhook{} o.PreUpdate() } + +func TestOutgoingWebhookTriggerWordStartsWith(t *testing.T) { + o := OutgoingWebhook{Id: NewId()} + o.TriggerWords = append(o.TriggerWords, "foo") + if !o.TriggerWordStartsWith("foobar") { + t.Fatal("Should return true") + } + if o.TriggerWordStartsWith("barfoo") { + t.Fatal("Should return false") + } +} diff --git a/store/sql_webhook_store.go b/store/sql_webhook_store.go index 72897771d3..74432b5417 100644 --- a/store/sql_webhook_store.go +++ b/store/sql_webhook_store.go @@ -34,6 +34,7 @@ func NewSqlWebhookStore(sqlStore *SqlStore) WebhookStore { tableo.ColMap("DisplayName").SetMaxSize(64) tableo.ColMap("Description").SetMaxSize(128) tableo.ColMap("ContentType").SetMaxSize(128) + tableo.ColMap("TriggerWhen").SetMaxSize(1) } return s @@ -46,6 +47,7 @@ func (s SqlWebhookStore) UpgradeSchemaIfNeeded() { s.CreateColumnIfNotExists("OutgoingWebhooks", "DisplayName", "varchar(64)", "varchar(64)", "") s.CreateColumnIfNotExists("OutgoingWebhooks", "Description", "varchar(128)", "varchar(128)", "") s.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "") + s.CreateColumnIfNotExists("OutgoingWebhooks", "TriggerWhen", "tinyint", "tinyint", "0") } func (s SqlWebhookStore) CreateIndexesIfNotExists() { diff --git a/webapp/components/integrations/components/add_outgoing_webhook.jsx b/webapp/components/integrations/components/add_outgoing_webhook.jsx index d6c0242a57..6f9750a90d 100644 --- a/webapp/components/integrations/components/add_outgoing_webhook.jsx +++ b/webapp/components/integrations/components/add_outgoing_webhook.jsx @@ -29,6 +29,7 @@ export default class AddOutgoingWebhook extends React.Component { this.updateContentType = this.updateContentType.bind(this); this.updateChannelId = this.updateChannelId.bind(this); this.updateTriggerWords = this.updateTriggerWords.bind(this); + this.updateTriggerWhen = this.updateTriggerWhen.bind(this); this.updateCallbackUrls = this.updateCallbackUrls.bind(this); this.state = { @@ -37,6 +38,7 @@ export default class AddOutgoingWebhook extends React.Component { contentType: 'application/x-www-form-urlencoded', channelId: '', triggerWords: '', + triggerWhen: 0, callbackUrls: '', saving: false, serverError: '', @@ -108,6 +110,7 @@ export default class AddOutgoingWebhook extends React.Component { const hook = { channel_id: this.state.channelId, trigger_words: triggerWords, + trigger_when: parseInt(this.state.triggerWhen, 10), callback_urls: callbackUrls, display_name: this.state.displayName, content_type: this.state.contentType, @@ -158,6 +161,12 @@ export default class AddOutgoingWebhook extends React.Component { }); } + updateTriggerWhen(e) { + this.setState({ + triggerWhen: e.target.value + }); + } + updateCallbackUrls(e) { this.setState({ callbackUrls: e.target.value @@ -297,6 +306,41 @@ export default class AddOutgoingWebhook extends React.Component { /> +
+ +
+ +
+