github.com/demisto/mattermost-server@v4.9.0-rc3+incompatible/model/search_params.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package model
     5  
     6  import (
     7  	"regexp"
     8  	"strings"
     9  )
    10  
    11  var searchTermPuncStart = regexp.MustCompile(`^[^\pL\d\s#"]+`)
    12  var searchTermPuncEnd = regexp.MustCompile(`[^\pL\d\s*"]+$`)
    13  
    14  type SearchParams struct {
    15  	Terms      string
    16  	IsHashtag  bool
    17  	InChannels []string
    18  	FromUsers  []string
    19  	OrTerms    bool
    20  }
    21  
    22  var searchFlags = [...]string{"from", "channel", "in"}
    23  
    24  func splitWords(text string) []string {
    25  	words := []string{}
    26  
    27  	foundQuote := false
    28  	location := 0
    29  	for i, char := range text {
    30  		if char == '"' {
    31  			if foundQuote {
    32  				// Grab the quoted section
    33  				word := text[location : i+1]
    34  				words = append(words, word)
    35  				foundQuote = false
    36  				location = i + 1
    37  			} else {
    38  				words = append(words, strings.Fields(text[location:i])...)
    39  				foundQuote = true
    40  				location = i
    41  			}
    42  		}
    43  	}
    44  
    45  	words = append(words, strings.Fields(text[location:])...)
    46  
    47  	return words
    48  }
    49  
    50  func parseSearchFlags(input []string) ([]string, [][2]string) {
    51  	words := []string{}
    52  	flags := [][2]string{}
    53  
    54  	skipNextWord := false
    55  	for i, word := range input {
    56  		if skipNextWord {
    57  			skipNextWord = false
    58  			continue
    59  		}
    60  
    61  		isFlag := false
    62  
    63  		if colon := strings.Index(word, ":"); colon != -1 {
    64  			flag := word[:colon]
    65  			value := word[colon+1:]
    66  
    67  			for _, searchFlag := range searchFlags {
    68  				// check for case insensitive equality
    69  				if strings.EqualFold(flag, searchFlag) {
    70  					if value != "" {
    71  						flags = append(flags, [2]string{searchFlag, value})
    72  						isFlag = true
    73  					} else if i < len(input)-1 {
    74  						flags = append(flags, [2]string{searchFlag, input[i+1]})
    75  						skipNextWord = true
    76  						isFlag = true
    77  					}
    78  
    79  					if isFlag {
    80  						break
    81  					}
    82  				}
    83  			}
    84  		}
    85  
    86  		if !isFlag {
    87  			// trim off surrounding punctuation (note that we leave trailing asterisks to allow wildcards)
    88  			word = searchTermPuncStart.ReplaceAllString(word, "")
    89  			word = searchTermPuncEnd.ReplaceAllString(word, "")
    90  
    91  			// and remove extra pound #s
    92  			word = hashtagStart.ReplaceAllString(word, "#")
    93  
    94  			if len(word) != 0 {
    95  				words = append(words, word)
    96  			}
    97  		}
    98  	}
    99  
   100  	return words, flags
   101  }
   102  
   103  func ParseSearchParams(text string) []*SearchParams {
   104  	words, flags := parseSearchFlags(splitWords(text))
   105  
   106  	hashtagTermList := []string{}
   107  	plainTermList := []string{}
   108  
   109  	for _, word := range words {
   110  		if validHashtag.MatchString(word) {
   111  			hashtagTermList = append(hashtagTermList, word)
   112  		} else {
   113  			plainTermList = append(plainTermList, word)
   114  		}
   115  	}
   116  
   117  	hashtagTerms := strings.Join(hashtagTermList, " ")
   118  	plainTerms := strings.Join(plainTermList, " ")
   119  
   120  	inChannels := []string{}
   121  	fromUsers := []string{}
   122  
   123  	for _, flagPair := range flags {
   124  		flag := flagPair[0]
   125  		value := flagPair[1]
   126  
   127  		if flag == "in" || flag == "channel" {
   128  			inChannels = append(inChannels, value)
   129  		} else if flag == "from" {
   130  			fromUsers = append(fromUsers, value)
   131  		}
   132  	}
   133  
   134  	paramsList := []*SearchParams{}
   135  
   136  	if len(plainTerms) > 0 {
   137  		paramsList = append(paramsList, &SearchParams{
   138  			Terms:      plainTerms,
   139  			IsHashtag:  false,
   140  			InChannels: inChannels,
   141  			FromUsers:  fromUsers,
   142  		})
   143  	}
   144  
   145  	if len(hashtagTerms) > 0 {
   146  		paramsList = append(paramsList, &SearchParams{
   147  			Terms:      hashtagTerms,
   148  			IsHashtag:  true,
   149  			InChannels: inChannels,
   150  			FromUsers:  fromUsers,
   151  		})
   152  	}
   153  
   154  	// special case for when no terms are specified but we still have a filter
   155  	if len(plainTerms) == 0 && len(hashtagTerms) == 0 && (len(inChannels) != 0 || len(fromUsers) != 0) {
   156  		paramsList = append(paramsList, &SearchParams{
   157  			Terms:      "",
   158  			IsHashtag:  false,
   159  			InChannels: inChannels,
   160  			FromUsers:  fromUsers,
   161  		})
   162  	}
   163  
   164  	return paramsList
   165  }