github.com/levb/mattermost-server@v5.3.1+incompatible/app/slack.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"regexp"
     8  
     9  	"fmt"
    10  	"strings"
    11  
    12  	"github.com/mattermost/mattermost-server/model"
    13  	"github.com/mattermost/mattermost-server/store"
    14  )
    15  
    16  func (a *App) ProcessSlackText(text string) string {
    17  	text = expandAnnouncement(text)
    18  	text = replaceUserIds(a.Srv.Store.User(), text)
    19  
    20  	return text
    21  }
    22  
    23  // Expand announcements in incoming webhooks from Slack. Those announcements
    24  // can be found in the text attribute, or in the pretext, text, title and value
    25  // attributes of the attachment structure. The Slack attachment structure is
    26  // documented here: https://api.slack.com/docs/attachments
    27  func (app *App) ProcessSlackAttachments(a []*model.SlackAttachment) []*model.SlackAttachment {
    28  	var nonNilAttachments = model.StringifySlackFieldValue(a)
    29  	for _, attachment := range a {
    30  		attachment.Pretext = app.ProcessSlackText(attachment.Pretext)
    31  		attachment.Text = app.ProcessSlackText(attachment.Text)
    32  		attachment.Title = app.ProcessSlackText(attachment.Title)
    33  
    34  		for _, field := range attachment.Fields {
    35  			if field.Value != nil {
    36  				// Ensure the value is set to a string if it is set
    37  				field.Value = app.ProcessSlackText(fmt.Sprintf("%v", field.Value))
    38  			}
    39  		}
    40  	}
    41  	return nonNilAttachments
    42  }
    43  
    44  // To mention @channel or @here via a webhook in Slack, the message should contain
    45  // <!channel> or <!here>, as explained at the bottom of this article:
    46  // https://get.slack.help/hc/en-us/articles/202009646-Making-announcements
    47  func expandAnnouncement(text string) string {
    48  	a1 := [3]string{"<!channel>", "<!here>", "<!all>"}
    49  	a2 := [3]string{"@channel", "@here", "@all"}
    50  
    51  	for i, a := range a1 {
    52  		text = strings.Replace(text, a, a2[i], -1)
    53  	}
    54  	return text
    55  }
    56  
    57  // Replaces user IDs mentioned like this <@userID> to a normal username (eg. @bob)
    58  // This is required so that Mattermost maintains Slack compatibility
    59  // Refer to: https://api.slack.com/changelog/2017-09-the-one-about-usernames
    60  func replaceUserIds(userStore store.UserStore, text string) string {
    61  	rgx, err := regexp.Compile("<@([a-zA-Z0-9]+)>")
    62  	if err == nil {
    63  		userIds := make([]string, 0)
    64  		matches := rgx.FindAllStringSubmatch(text, -1)
    65  		for _, match := range matches {
    66  			userIds = append(userIds, match[1])
    67  		}
    68  
    69  		if res := <-userStore.GetProfileByIds(userIds, true); res.Err == nil {
    70  			for _, user := range res.Data.([]*model.User) {
    71  				text = strings.Replace(text, "<@"+user.Id+">", "@"+user.Username, -1)
    72  			}
    73  		}
    74  	}
    75  	return text
    76  }