mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Added from:, in:, and channel: search modifiers
This commit is contained in:
130
model/search_params.go
Normal file
130
model/search_params.go
Normal file
@@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SearchParams struct {
|
||||
Terms string
|
||||
IsHashtag bool
|
||||
InChannel string
|
||||
FromUser string
|
||||
}
|
||||
|
||||
var searchFlags = [...]string{"from", "channel", "in"}
|
||||
|
||||
func splitWords(text string) []string {
|
||||
words := []string{}
|
||||
|
||||
for _, word := range strings.Fields(text) {
|
||||
word = puncStart.ReplaceAllString(word, "")
|
||||
word = puncEnd.ReplaceAllString(word, "")
|
||||
|
||||
if len(word) != 0 {
|
||||
words = append(words, word)
|
||||
}
|
||||
}
|
||||
|
||||
return words
|
||||
}
|
||||
|
||||
func parseSearchFlags(input []string) ([]string, map[string]string) {
|
||||
words := []string{}
|
||||
flags := make(map[string]string)
|
||||
|
||||
skipNextWord := false
|
||||
for i, word := range input {
|
||||
if skipNextWord {
|
||||
skipNextWord = false
|
||||
continue
|
||||
}
|
||||
|
||||
isFlag := false
|
||||
|
||||
if colon := strings.Index(word, ":"); colon != -1 {
|
||||
flag := word[:colon]
|
||||
value := word[colon+1:]
|
||||
|
||||
for _, searchFlag := range searchFlags {
|
||||
// check for case insensitive equality
|
||||
if strings.EqualFold(flag, searchFlag) {
|
||||
if value != "" {
|
||||
flags[searchFlag] = value
|
||||
isFlag = true
|
||||
} else if i < len(input)-1 {
|
||||
flags[searchFlag] = input[i+1]
|
||||
skipNextWord = true
|
||||
isFlag = true
|
||||
}
|
||||
|
||||
if isFlag {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !isFlag {
|
||||
words = append(words, word)
|
||||
}
|
||||
}
|
||||
|
||||
return words, flags
|
||||
}
|
||||
|
||||
func ParseSearchParams(text string) (*SearchParams, *SearchParams) {
|
||||
words, flags := parseSearchFlags(splitWords(text))
|
||||
|
||||
hashtagTerms := []string{}
|
||||
plainTerms := []string{}
|
||||
|
||||
for _, word := range words {
|
||||
if validHashtag.MatchString(word) {
|
||||
hashtagTerms = append(hashtagTerms, word)
|
||||
} else {
|
||||
plainTerms = append(plainTerms, word)
|
||||
}
|
||||
}
|
||||
|
||||
inChannel := flags["channel"]
|
||||
if inChannel == "" {
|
||||
inChannel = flags["in"]
|
||||
}
|
||||
|
||||
fromUser := flags["from"]
|
||||
|
||||
var plainParams *SearchParams
|
||||
if len(plainTerms) > 0 {
|
||||
plainParams = &SearchParams{
|
||||
Terms: strings.Join(plainTerms, " "),
|
||||
IsHashtag: false,
|
||||
InChannel: inChannel,
|
||||
FromUser: fromUser,
|
||||
}
|
||||
}
|
||||
|
||||
var hashtagParams *SearchParams
|
||||
if len(hashtagTerms) > 0 {
|
||||
hashtagParams = &SearchParams{
|
||||
Terms: strings.Join(hashtagTerms, " "),
|
||||
IsHashtag: true,
|
||||
InChannel: inChannel,
|
||||
FromUser: fromUser,
|
||||
}
|
||||
}
|
||||
|
||||
// special case for when no terms are specified but we still have a filter
|
||||
if plainParams == nil && hashtagParams == nil && (inChannel != "" || fromUser != "") {
|
||||
plainParams = &SearchParams{
|
||||
Terms: "",
|
||||
IsHashtag: false,
|
||||
InChannel: inChannel,
|
||||
FromUser: fromUser,
|
||||
}
|
||||
}
|
||||
|
||||
return plainParams, hashtagParams
|
||||
}
|
||||
70
model/search_params_test.go
Normal file
70
model/search_params_test.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseSearchFlags(t *testing.T) {
|
||||
if words, flags := parseSearchFlags(splitWords("")); len(words) != 0 {
|
||||
t.Fatal("got words from empty input")
|
||||
} else if len(flags) != 0 {
|
||||
t.Fatal("got flags from empty input")
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("word")); len(words) != 1 || words[0] != "word" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 0 {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana cherry")); len(words) != 3 || words[0] != "apple" || words[1] != "banana" || words[2] != "cherry" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 0 {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana from:chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["from"] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana from: chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["from"] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana in: chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["in"] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("apple banana channel:chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 1 || flags["channel"] != "chan" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("fruit: cherry")); len(words) != 2 || words[0] != "fruit:" || words[1] != "cherry" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 0 {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("channel:")); len(words) != 1 || words[0] != "channel:" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 0 {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
|
||||
if words, flags := parseSearchFlags(splitWords("channel: first in: second from:")); len(words) != 1 || words[0] != "from:" {
|
||||
t.Fatalf("got incorrect words %v", words)
|
||||
} else if len(flags) != 2 || flags["channel"] != "first" || flags["in"] != "second" {
|
||||
t.Fatalf("got incorrect flags %v", flags)
|
||||
}
|
||||
}
|
||||
@@ -242,10 +242,10 @@ func Etag(parts ...interface{}) string {
|
||||
|
||||
var validHashtag = regexp.MustCompile(`^(#[A-Za-z]+[A-Za-z0-9_\-]*[A-Za-z0-9])$`)
|
||||
var puncStart = regexp.MustCompile(`^[.,()&$!\[\]{}"':;\\]+`)
|
||||
var puncEnd = regexp.MustCompile(`[.,()&$#!\[\]{}"':;\\]+$`)
|
||||
var puncEnd = regexp.MustCompile(`[.,()&$#!\[\]{}"';\\]+$`)
|
||||
|
||||
func ParseHashtags(text string) (string, string) {
|
||||
words := strings.Split(strings.Replace(text, "\n", " ", -1), " ")
|
||||
words := strings.Fields(text)
|
||||
|
||||
hashtagString := ""
|
||||
plainString := ""
|
||||
|
||||
Reference in New Issue
Block a user