diff options
author | Pierre Rudloff <contact@rudloff.pro> | 2016-07-26 14:04:28 +0200 |
---|---|---|
committer | Christopher Speller <crspeller@gmail.com> | 2016-07-26 08:04:28 -0400 |
commit | 564dffec35d2ab6772c2561f28d9ad9a2bcbeb40 (patch) | |
tree | 6e6caeee6f96707bc5faad7f984e673026e7806e | |
parent | c56b429e1dee257bac69de1db55cafee01ccd005 (diff) | |
download | chat-564dffec35d2ab6772c2561f28d9ad9a2bcbeb40.tar.gz chat-564dffec35d2ab6772c2561f28d9ad9a2bcbeb40.tar.bz2 chat-564dffec35d2ab6772c2561f28d9ad9a2bcbeb40.zip |
Add option to trigger outgoing webhook if first word starts with trigger word (#3611)
-rw-r--r-- | api/post.go | 15 | ||||
-rw-r--r-- | model/outgoing_webhook.go | 20 | ||||
-rw-r--r-- | model/outgoing_webhook_test.go | 11 | ||||
-rw-r--r-- | store/sql_webhook_store.go | 2 | ||||
-rw-r--r-- | webapp/components/integrations/components/add_outgoing_webhook.jsx | 44 | ||||
-rw-r--r-- | webapp/components/integrations/components/installed_outgoing_webhook.jsx | 30 | ||||
-rw-r--r-- | webapp/i18n/en.json | 4 | ||||
-rw-r--r-- | webapp/sass/routes/_backstage.scss | 1 |
8 files changed, 123 insertions, 4 deletions
diff --git a/api/post.go b/api/post.go index 9bf6cff40..c363ff076 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 ee7a32f1f..ec2ed75c7 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 24b81d221..2458c62e4 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 72897771d..74432b541 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 d6c0242a5..6f9750a90 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 @@ -300,6 +309,41 @@ export default class AddOutgoingWebhook extends React.Component { <div className='form-group'> <label className='control-label col-sm-4' + htmlFor='triggerWords' + > + <FormattedMessage + id='add_outgoing_webhook.triggerWordsTriggerWhen' + defaultMessage='Trigger When' + /> + </label> + <div className='col-md-5 col-sm-8'> + <select + className='form-control' + value={this.state.triggerWhen} + onChange={this.updateTriggerWhen} + > + <option + value='0' + > + <FormattedMessage + id='add_outgoing_webhook.triggerWordsTriggerWhenFullWord' + defaultMessage='First word matches a trigger word exactly' + /> + </option> + <option + value='1' + > + <FormattedMessage + id='add_outgoing_webhook.triggerWordsTriggerWhenStartsWith' + defaultMessage='First word starts with a trigger word' + /> + </option> + </select> + </div> + </div> + <div className='form-group'> + <label + className='control-label col-sm-4' htmlFor='callbackUrls' > <FormattedMessage diff --git a/webapp/components/integrations/components/installed_outgoing_webhook.jsx b/webapp/components/integrations/components/installed_outgoing_webhook.jsx index 852231823..4b478255c 100644 --- a/webapp/components/integrations/components/installed_outgoing_webhook.jsx +++ b/webapp/components/integrations/components/installed_outgoing_webhook.jsx @@ -66,6 +66,8 @@ export default class InstalledOutgoingWebhook extends React.Component { const outgoingWebhook = this.props.outgoingWebhook; const channel = ChannelStore.get(outgoingWebhook.channel_id); const filter = this.props.filter ? this.props.filter.toLowerCase() : ''; + const triggerWordsFull = 0; + const triggerWordsStartsWith = 1; if (!this.matchesFilter(outgoingWebhook, channel, filter)) { return null; @@ -127,6 +129,23 @@ export default class InstalledOutgoingWebhook extends React.Component { </div> ); + let triggerWhen; + if (outgoingWebhook.trigger_when === triggerWordsFull) { + triggerWhen = ( + <FormattedMessage + id='add_outgoing_webhook.triggerWordsTriggerWhenFullWord' + defaultMessage='First word matches a trigger word exactly' + /> + ); + } else if (outgoingWebhook.trigger_when === triggerWordsStartsWith) { + triggerWhen = ( + <FormattedMessage + id='add_outgoing_webhook.triggerWordsTriggerWhenStartsWith' + defaultMessage='First word starts with a trigger word' + /> + ); + } + return ( <div className='backstage-list__item'> <div className='item-details'> @@ -149,6 +168,17 @@ export default class InstalledOutgoingWebhook extends React.Component { </div> {triggerWords} <div className='item-details__row'> + <span className='item-details__trigger-when'> + <FormattedMessage + id='installed_integrations.triggerWhen' + defaultMessage='Trigger When: {triggerWhen}' + values={{ + triggerWhen + }} + /> + </span> + </div> + <div className='item-details__row'> <span className='item-details__token'> <FormattedMessage id='installed_integrations.token' diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index 371f471cd..1b13a1c59 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -98,6 +98,9 @@ "add_outgoing_webhook.save": "Save", "add_outgoing_webhook.triggerWords": "Trigger Words (One Per Line)", "add_outgoing_webhook.triggerWordsOrChannelRequired": "A valid channel or a list of trigger words is required", + "add_outgoing_webhook.triggerWordsTriggerWhen": "Trigger When", + "add_outgoing_webhook.triggerWordsTriggerWhenFullWord": "First word matches a trigger word exactly", + "add_outgoing_webhook.triggerWordsTriggerWhenStartsWith": "First word starts with a trigger word", "admin.audits.reload": "Reload User Activity Logs", "admin.audits.title": "User Activity Logs", "admin.authentication.email": "Email Auth", @@ -1109,6 +1112,7 @@ "installed_integrations.regenToken": "Regenerate Token", "installed_integrations.token": "Token: {token}", "installed_integrations.triggerWords": "Trigger Words: {triggerWords}", + "installed_integrations.triggerWhen": "Trigger When: {triggerWhen}", "installed_integrations.url": "URL: {url}", "installed_outgoing_webhooks.add": "Add Outgoing Webhook", "installed_outgoing_webhooks.empty": "No outgoing webhooks found", diff --git a/webapp/sass/routes/_backstage.scss b/webapp/sass/routes/_backstage.scss index 5edba2660..4b8c6ff6c 100644 --- a/webapp/sass/routes/_backstage.scss +++ b/webapp/sass/routes/_backstage.scss @@ -247,6 +247,7 @@ .item-details__content_type, .item-details__token, .item-details__trigger-words, + .item-details__trigger-when, .item-details__url, .item-details__creation { display: inline-block; |