PLT-6271 Changed word splitting to initially split on any non-name character (#6261)

* PLT-6271 Changed word splitting to initially split on any non-name character

* Fixed detection of out of channel mentions
Этот коммит содержится в:
Harrison Healey
2017-04-28 10:13:07 -04:00
коммит произвёл Christopher Speller
родитель 83bfd95f65
Коммит c3e17da8c8
4 изменённых файлов: 38 добавлений и 36 удалений

Просмотреть файл

@@ -665,8 +665,8 @@ func GetExplicitMentions(message string, keywords map[string][]string) (map[stri
message = removeCodeFromMessage(message) message = removeCodeFromMessage(message)
for _, word := range strings.FieldsFunc(message, func(c rune) bool { for _, word := range strings.FieldsFunc(message, func(c rune) bool {
// Split on whitespace (as strings.Fields normally does) or on Markdown characters // Split on any whitespace or punctuation that can't be part of an at mention
return unicode.IsSpace(c) || c == '*' || c == '~' return !(c == '.' || c == '-' || c == '_' || c == '@' || unicode.IsLetter(c) || unicode.IsNumber(c))
}) { }) {
isMention := false isMention := false
@@ -694,11 +694,14 @@ func GetExplicitMentions(message string, keywords map[string][]string) (map[stri
isMention = true isMention = true
} }
if !isMention { if isMention {
// No matches were found with the string split just on whitespace so try further splitting continue
// the message on punctuation }
if strings.ContainsAny(word, ".-") {
// This word contains a character that may be the end of a sentence, so split further
splitWords := strings.FieldsFunc(word, func(c rune) bool { splitWords := strings.FieldsFunc(word, func(c rune) bool {
return model.SplitRunes[c] return c == '.' || c == '-'
}) })
for _, splitWord := range splitWords { for _, splitWord := range splitWords {
@@ -727,6 +730,9 @@ func GetExplicitMentions(message string, keywords map[string][]string) (map[stri
potentialOthersMentioned = append(potentialOthersMentioned, username) potentialOthersMentioned = append(potentialOthersMentioned, username)
} }
} }
} else if _, ok := systemMentions[word]; !ok && strings.HasPrefix(word, "@") {
username := word[1:]
potentialOthersMentioned = append(potentialOthersMentioned, username)
} }
} }

Просмотреть файл

@@ -168,40 +168,38 @@ func TestGetExplicitMentionsAtHere(t *testing.T) {
"here": false, "here": false,
"@here": true, "@here": true,
" @here ": true, " @here ": true,
"\t@here\t": true,
"\n@here\n": true, "\n@here\n": true,
// "!@here!": true, "!@here!": true,
// "@@here@": true, "#@here#": true,
// "#@here#": true, "$@here$": true,
// "$@here$": true, "%@here%": true,
// "%@here%": true, "^@here^": true,
// "^@here^": true, "&@here&": true,
// "&@here&": true, "*@here*": true,
// "*@here*": true, "(@here(": true,
"(@here(": true, ")@here)": true,
")@here)": true, "-@here-": true,
// "-@here-": true, "_@here_": false, // This case shouldn't mention since it would be mentioning "@here_"
// "_@here_": true, "=@here=": true,
// "=@here=": true,
"+@here+": true, "+@here+": true,
"[@here[": true, "[@here[": true,
"{@here{": true, "{@here{": true,
"]@here]": true, "]@here]": true,
"}@here}": true, "}@here}": true,
"\\@here\\": true, "\\@here\\": true,
// "|@here|": true, "|@here|": true,
";@here;": true, ";@here;": true,
":@here:": true, ":@here:": true,
// "'@here'": true, "'@here'": true,
// "\"@here\"": true, "\"@here\"": true,
",@here,": true, ",@here,": true,
"<@here<": true, "<@here<": true,
".@here.": true, ".@here.": true,
">@here>": true, ">@here>": true,
"/@here/": true, "/@here/": true,
"?@here?": true, "?@here?": true,
// "`@here`": true, "`@here`": false, // This case shouldn't mention since it's a code block
// "~@here~": true, "~@here~": true,
} }
for message, shouldMention := range cases { for message, shouldMention := range cases {

Просмотреть файл

@@ -5,9 +5,9 @@ package app
import ( import (
"bytes" "bytes"
"encoding/json"
"image" "image"
"image/color" "image/color"
"encoding/json"
"math/rand" "math/rand"
"strings" "strings"
"testing" "testing"

Просмотреть файл

@@ -401,8 +401,6 @@ func ClearMentionTags(post string) string {
var UrlRegex = regexp.MustCompile(`^((?:[a-z]+:\/\/)?(?:(?:[a-z0-9\-]+\.)+(?:[a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(?:\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(?:\?[a-z0-9+_~\-\.%=&amp;]*)?)?(?:#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(?:\s+|$)$`) var UrlRegex = regexp.MustCompile(`^((?:[a-z]+:\/\/)?(?:(?:[a-z0-9\-]+\.)+(?:[a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(?:\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(?:\?[a-z0-9+_~\-\.%=&amp;]*)?)?(?:#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(?:\s+|$)$`)
var PartialUrlRegex = regexp.MustCompile(`/([A-Za-z0-9]{26})/([A-Za-z0-9]{26})/((?:[A-Za-z0-9]{26})?.+(?:\.[A-Za-z0-9]{3,})?)`) var PartialUrlRegex = regexp.MustCompile(`/([A-Za-z0-9]{26})/([A-Za-z0-9]{26})/((?:[A-Za-z0-9]{26})?.+(?:\.[A-Za-z0-9]{3,})?)`)
var SplitRunes = map[rune]bool{',': true, ' ': true, '.': true, '!': true, '?': true, ':': true, ';': true, '\n': true, '<': true, '>': true, '(': true, ')': true, '{': true, '}': true, '[': true, ']': true, '+': true, '/': true, '\\': true, '^': true, '#': true, '$': true, '&': true}
func IsValidHttpUrl(rawUrl string) bool { func IsValidHttpUrl(rawUrl string) bool {
if strings.Index(rawUrl, "http://") != 0 && strings.Index(rawUrl, "https://") != 0 { if strings.Index(rawUrl, "http://") != 0 && strings.Index(rawUrl, "https://") != 0 {
return false return false