[MM-20684] Slash Command Autocomplete (#14557)

* [MM-20684] Initial implementation of the Command Autocomplete (#13602)

* Implement Autocomplete Data

* Change CommandName to Trigger

* Fix Autocomplete test

* Make stylistic changes

* Rename a bunch of fields and methods

* Fix variable names, safer type assertions

* [MM-20684] plugin autocomplete implementation (#14259)

* Add an endpoint for command autocomplete suggestions

* Add full Suggestion to the AutocompleteSugestion struct

* Add Dynamic Argument support

* Tidy up things

* Fix missed test case

* Add support of the named arguments

* Update autocomplete API

Fix review issues

Implement dynamic args as a local request

* Fix ineffassign

* Add support of the uppercase letters in arguments

* Add support of the optional arguments

* Remove ineffectual assignment

* Add support for icons (#14489)

* Address couple of nits

* Add comment to IconData

* Add types to all consts

Co-authored-by: mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Shota Gvinepadze
2020-05-21 12:24:56 +04:00
коммит произвёл GitHub
родитель e8daab6b84
Коммит 43e606173b
16 изменённых файлов: 1663 добавлений и 33 удалений

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

@@ -190,6 +190,8 @@ type AppIface interface {
// GetSessionLengthInMillis returns the session length, in milliseconds,
// based on the type of session (Mobile, SSO, Web/LDAP).
GetSessionLengthInMillis(session *model.Session) int64
// GetSuggestions returns suggestions for user input.
GetSuggestions(commands []*model.Command, userInput, roleID string) []model.AutocompleteSuggestion
// GetTeamGroupUsers returns the users who are associated to the team via GroupTeams and GroupMembers.
GetTeamGroupUsers(teamID string) ([]*model.User, *model.AppError)
// GetTeamSchemeChannelRoles Checks if a team has an override scheme and returns the scheme channel role names or default channel role names.

253
app/command_autocomplete.go Обычный файл
Просмотреть файл

@@ -0,0 +1,253 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"net/url"
"sort"
"strings"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model"
)
// GetSuggestions returns suggestions for user input.
func (a *App) GetSuggestions(commands []*model.Command, userInput, roleID string) []model.AutocompleteSuggestion {
sort.Slice(commands, func(i, j int) bool {
return strings.Compare(strings.ToLower(commands[i].Trigger), strings.ToLower(commands[j].Trigger)) < 0
})
autocompleteData := []*model.AutocompleteData{}
for _, command := range commands {
if command.AutocompleteData == nil {
command.AutocompleteData = model.NewAutocompleteData(command.Trigger, command.AutoCompleteHint, command.AutoCompleteDesc)
}
autocompleteData = append(autocompleteData, command.AutocompleteData)
}
suggestions := a.getSuggestions(autocompleteData, "", userInput, roleID)
for i, suggestion := range suggestions {
for _, command := range commands {
if strings.HasPrefix(suggestion.Complete, command.Trigger) {
suggestions[i].IconData = command.AutocompleteIconData
break
}
}
}
return suggestions
}
func (a *App) getSuggestions(commands []*model.AutocompleteData, inputParsed, inputToBeParsed, roleID string) []model.AutocompleteSuggestion {
suggestions := []model.AutocompleteSuggestion{}
index := strings.Index(inputToBeParsed, " ")
if index == -1 { // no space in input
for _, command := range commands {
if strings.HasPrefix(command.Trigger, strings.ToLower(inputToBeParsed)) && (command.RoleID == roleID || roleID == model.SYSTEM_ADMIN_ROLE_ID || roleID == "") {
s := model.AutocompleteSuggestion{
Complete: inputParsed + command.Trigger,
Suggestion: command.Trigger,
Description: command.HelpText,
Hint: command.Hint,
}
suggestions = append(suggestions, s)
}
}
return suggestions
}
for _, command := range commands {
if command.Trigger != strings.ToLower(inputToBeParsed[:index]) {
continue
}
if roleID != "" && roleID != model.SYSTEM_ADMIN_ROLE_ID && roleID != command.RoleID {
continue
}
toBeParsed := inputToBeParsed[index+1:]
parsed := inputParsed + inputToBeParsed[:index+1]
if len(command.Arguments) == 0 {
// Seek recursively in subcommands
subSuggestions := a.getSuggestions(command.SubCommands, parsed, toBeParsed, roleID)
suggestions = append(suggestions, subSuggestions...)
continue
}
found, _, _, suggestion := a.parseArguments(command.Arguments, parsed, toBeParsed)
if found {
suggestions = append(suggestions, suggestion...)
}
}
return suggestions
}
func (a *App) parseArguments(args []*model.AutocompleteArg, parsed, toBeParsed string) (found bool, alreadyParsed string, yetToBeParsed string, suggestions []model.AutocompleteSuggestion) {
if len(args) == 0 {
return false, parsed, toBeParsed, suggestions
}
if args[0].Required {
found, changedParsed, changedToBeParsed, suggestion := a.parseArgument(args[0], parsed, toBeParsed)
if found {
suggestions = append(suggestions, suggestion...)
return true, changedParsed, changedToBeParsed, suggestions
}
return a.parseArguments(args[1:], changedParsed, changedToBeParsed)
}
// Handling optional arguments. Optional argument can be inputted or not,
// so we have to pase both cases recursively and output combined suggestions.
foundWithOptional, changedParsedWithOptional, changedToBeParsedWithOptional, suggestionsWithOptional := a.parseArgument(args[0], parsed, toBeParsed)
if foundWithOptional {
suggestions = append(suggestions, suggestionsWithOptional...)
} else {
foundWithOptionalRest, changedParsedWithOptionalRest, changedToBeParsedWithOptionalRest, suggestionsWithOptionalRest := a.parseArguments(args[1:], changedParsedWithOptional, changedToBeParsedWithOptional)
if foundWithOptionalRest {
suggestions = append(suggestions, suggestionsWithOptionalRest...)
}
foundWithOptional = foundWithOptionalRest
changedParsedWithOptional = changedParsedWithOptionalRest
changedToBeParsedWithOptional = changedToBeParsedWithOptionalRest
}
foundWithoutOptional, changedParsedWithoutOptional, changedToBeParsedWithoutOptional, suggestionsWithoutOptional := a.parseArguments(args[1:], parsed, toBeParsed)
if foundWithoutOptional {
suggestions = append(suggestions, suggestionsWithoutOptional...)
}
// if suggestions were found we can return them
if foundWithOptional || foundWithoutOptional {
return true, parsed + toBeParsed, "", suggestions
}
// no suggestions found yet, check if optional argument was inputted
if changedParsedWithOptional != parsed && changedToBeParsedWithOptional != toBeParsed {
return false, changedParsedWithOptional, changedToBeParsedWithOptional, suggestions
}
// no suggestions and optional argument was not inputted
return foundWithoutOptional, changedParsedWithoutOptional, changedToBeParsedWithoutOptional, suggestions
}
func (a *App) parseArgument(arg *model.AutocompleteArg, parsed, toBeParsed string) (found bool, alreadyParsed string, yetToBeParsed string, suggestions []model.AutocompleteSuggestion) {
if arg.Name != "" { //Parse the --name first
found, changedParsed, changedToBeParsed, suggestion := parseNamedArgument(arg, parsed, toBeParsed)
if found {
suggestions = append(suggestions, suggestion)
return true, changedParsed, changedToBeParsed, suggestions
}
if changedToBeParsed == "" {
return true, changedParsed, changedToBeParsed, suggestions
}
if changedToBeParsed == " " {
changedToBeParsed = ""
}
parsed = changedParsed
toBeParsed = changedToBeParsed
}
if arg.Type == model.AutocompleteArgTypeText {
found, changedParsed, changedToBeParsed, suggestion := parseInputTextArgument(arg, parsed, toBeParsed)
if found {
suggestions = append(suggestions, suggestion)
return true, changedParsed, changedToBeParsed, suggestions
}
parsed = changedParsed
toBeParsed = changedToBeParsed
} else if arg.Type == model.AutocompleteArgTypeStaticList {
found, changedParsed, changedToBeParsed, staticListsuggestions := parseStaticListArgument(arg, parsed, toBeParsed)
if found {
suggestions = append(suggestions, staticListsuggestions...)
return true, changedParsed, changedToBeParsed, suggestions
}
parsed = changedParsed
toBeParsed = changedToBeParsed
} else if arg.Type == model.AutocompleteArgTypeDynamicList {
found, changedParsed, changedToBeParsed, dynamicListsuggestions := a.getDynamicListArgument(arg, parsed, toBeParsed)
if found {
suggestions = append(suggestions, dynamicListsuggestions...)
return true, changedParsed, changedToBeParsed, suggestions
}
parsed = changedParsed
toBeParsed = changedToBeParsed
}
return false, parsed, toBeParsed, suggestions
}
func parseNamedArgument(arg *model.AutocompleteArg, parsed, toBeParsed string) (found bool, alreadyParsed string, yetToBeParsed string, suggestion model.AutocompleteSuggestion) {
in := strings.TrimPrefix(toBeParsed, " ")
namedArg := "--" + arg.Name
if in == "" { //The user has not started typing the argument.
return true, parsed + toBeParsed, "", model.AutocompleteSuggestion{Complete: parsed + toBeParsed + namedArg + " ", Suggestion: namedArg, Hint: "", Description: arg.HelpText}
}
if strings.HasPrefix(strings.ToLower(namedArg), strings.ToLower(in)) {
return true, parsed + toBeParsed, "", model.AutocompleteSuggestion{Complete: parsed + toBeParsed + namedArg[len(in):] + " ", Suggestion: namedArg, Hint: "", Description: arg.HelpText}
}
if !strings.HasPrefix(strings.ToLower(in), strings.ToLower(namedArg)+" ") {
return false, parsed + toBeParsed, "", model.AutocompleteSuggestion{}
}
if strings.ToLower(in) == strings.ToLower(namedArg)+" " {
return false, parsed + namedArg + " ", " ", model.AutocompleteSuggestion{}
}
return false, parsed + namedArg + " ", in[len(namedArg)+1:], model.AutocompleteSuggestion{}
}
func parseInputTextArgument(arg *model.AutocompleteArg, parsed, toBeParsed string) (found bool, alreadyParsed string, yetToBeParsed string, suggestion model.AutocompleteSuggestion) {
in := strings.TrimPrefix(toBeParsed, " ")
a := arg.Data.(*model.AutocompleteTextArg)
if in == "" { //The user has not started typing the argument.
return true, parsed + toBeParsed, "", model.AutocompleteSuggestion{Complete: parsed + toBeParsed, Suggestion: "", Hint: a.Hint, Description: arg.HelpText}
}
if in[0] == '"' { //input with multiple words
indexOfSecondQuote := strings.Index(in[1:], `"`)
if indexOfSecondQuote == -1 { //typing of the multiple word argument is not finished
return true, parsed + toBeParsed, "", model.AutocompleteSuggestion{Complete: parsed + toBeParsed, Suggestion: "", Hint: a.Hint, Description: arg.HelpText}
}
// this argument is typed already
offset := 2
if len(in) > indexOfSecondQuote+2 && in[indexOfSecondQuote+2] == ' ' {
offset++
}
return false, parsed + in[:indexOfSecondQuote+offset], in[indexOfSecondQuote+offset:], model.AutocompleteSuggestion{}
}
// input with a single word
index := strings.Index(in, " ")
if index == -1 { // typing of the single word argument is not finished
return true, parsed + toBeParsed, "", model.AutocompleteSuggestion{Complete: parsed + toBeParsed, Suggestion: "", Hint: a.Hint, Description: arg.HelpText}
}
// single word argument already typed
return false, parsed + in[:index+1], in[index+1:], model.AutocompleteSuggestion{}
}
func parseStaticListArgument(arg *model.AutocompleteArg, parsed, toBeParsed string) (found bool, alreadyParsed string, yetToBeParsed string, suggestions []model.AutocompleteSuggestion) {
a := arg.Data.(*model.AutocompleteStaticListArg)
return parseListItems(a.PossibleArguments, parsed, toBeParsed)
}
func (a *App) getDynamicListArgument(arg *model.AutocompleteArg, parsed, toBeParsed string) (found bool, alreadyParsed string, yetToBeParsed string, suggestions []model.AutocompleteSuggestion) {
dynamicArg := arg.Data.(*model.AutocompleteDynamicListArg)
params := url.Values{}
params.Add("user_input", parsed+toBeParsed)
params.Add("parsed", parsed)
resp, err := a.doPluginRequest("GET", dynamicArg.FetchURL, params, nil)
if err != nil {
a.Log().Error("Can't fetch dynamic list arguments for", mlog.String("url", dynamicArg.FetchURL), mlog.Err(err))
return false, parsed, toBeParsed, []model.AutocompleteSuggestion{}
}
listItems := model.AutocompleteStaticListItemsFromJSON(resp.Body)
return parseListItems(listItems, parsed, toBeParsed)
}
func parseListItems(items []model.AutocompleteListItem, parsed, toBeParsed string) (bool, string, string, []model.AutocompleteSuggestion) {
in := strings.TrimPrefix(toBeParsed, " ")
suggestions := []model.AutocompleteSuggestion{}
maxPrefix := ""
for _, arg := range items {
if strings.HasPrefix(strings.ToLower(in), strings.ToLower(arg.Item)+" ") && len(maxPrefix) < len(arg.Item)+1 {
maxPrefix = arg.Item + " "
}
}
if maxPrefix != "" { //typing of an argument finished
return false, parsed + in[:len(maxPrefix)], in[len(maxPrefix):], []model.AutocompleteSuggestion{}
}
// user has not finished typing static argument
for _, arg := range items {
if strings.HasPrefix(strings.ToLower(arg.Item), strings.ToLower(in)) {
suggestions = append(suggestions, model.AutocompleteSuggestion{Complete: parsed + arg.Item, Suggestion: arg.Item, Hint: arg.Hint, Description: arg.HelpText})
}
}
return true, parsed + toBeParsed, "", suggestions
}

609
app/command_autocomplete_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,609 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"testing"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/stretchr/testify/assert"
)
func TestParseStaticListArgument(t *testing.T) {
items := []model.AutocompleteListItem{
{
Hint: "[hint]",
Item: "on",
HelpText: "help",
},
}
fixedArgs := &model.AutocompleteStaticListArg{PossibleArguments: items}
argument := &model.AutocompleteArg{
Name: "", //positional
HelpText: "some_help",
Type: model.AutocompleteArgTypeStaticList,
Data: fixedArgs,
}
found, _, _, suggestions := parseStaticListArgument(argument, "", "") //TODO understand this!
assert.True(t, found)
assert.Equal(t, []model.AutocompleteSuggestion{{Complete: "on", Suggestion: "on", Hint: "[hint]", Description: "help"}}, suggestions)
found, _, _, suggestions = parseStaticListArgument(argument, "", "o")
assert.True(t, found)
assert.Equal(t, []model.AutocompleteSuggestion{{Complete: "on", Suggestion: "on", Hint: "[hint]", Description: "help"}}, suggestions)
found, parsed, toBeParsed, _ := parseStaticListArgument(argument, "", "on ")
assert.False(t, found)
assert.Equal(t, "on ", parsed)
assert.Equal(t, "", toBeParsed)
found, parsed, toBeParsed, _ = parseStaticListArgument(argument, "", "on some")
assert.False(t, found)
assert.Equal(t, "on ", parsed)
assert.Equal(t, "some", toBeParsed)
fixedArgs.PossibleArguments = append(fixedArgs.PossibleArguments,
model.AutocompleteListItem{Hint: "[hint]", Item: "off", HelpText: "help"})
found, _, _, suggestions = parseStaticListArgument(argument, "", "o")
assert.True(t, found)
assert.Equal(t, []model.AutocompleteSuggestion{{Complete: "on", Suggestion: "on", Hint: "[hint]", Description: "help"}, {Complete: "off", Suggestion: "off", Hint: "[hint]", Description: "help"}}, suggestions)
found, _, _, suggestions = parseStaticListArgument(argument, "", "of")
assert.True(t, found)
assert.Equal(t, []model.AutocompleteSuggestion{{Complete: "off", Suggestion: "off", Hint: "[hint]", Description: "help"}}, suggestions)
found, _, _, suggestions = parseStaticListArgument(argument, "", "o some")
assert.True(t, found)
assert.Len(t, suggestions, 0)
found, parsed, toBeParsed, _ = parseStaticListArgument(argument, "", "off some")
assert.False(t, found)
assert.Equal(t, "off ", parsed)
assert.Equal(t, "some", toBeParsed)
fixedArgs.PossibleArguments = append(fixedArgs.PossibleArguments,
model.AutocompleteListItem{Hint: "[hint]", Item: "onon", HelpText: "help"})
found, _, _, suggestions = parseStaticListArgument(argument, "", "on")
assert.True(t, found)
assert.Equal(t, []model.AutocompleteSuggestion{{Complete: "on", Suggestion: "on", Hint: "[hint]", Description: "help"}, {Complete: "onon", Suggestion: "onon", Hint: "[hint]", Description: "help"}}, suggestions)
found, _, _, suggestions = parseStaticListArgument(argument, "bla ", "ono")
assert.True(t, found)
assert.Equal(t, []model.AutocompleteSuggestion{{Complete: "bla onon", Suggestion: "onon", Hint: "[hint]", Description: "help"}}, suggestions)
found, parsed, toBeParsed, _ = parseStaticListArgument(argument, "", "on some")
assert.False(t, found)
assert.Equal(t, "on ", parsed)
assert.Equal(t, "some", toBeParsed)
found, parsed, toBeParsed, _ = parseStaticListArgument(argument, "", "onon some")
assert.False(t, found)
assert.Equal(t, "onon ", parsed)
assert.Equal(t, "some", toBeParsed)
}
func TestParseInputTextArgument(t *testing.T) {
argument := &model.AutocompleteArg{
Name: "", //positional
HelpText: "some_help",
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{Hint: "hint", Pattern: "pat"},
}
found, _, _, suggestion := parseInputTextArgument(argument, "", "")
assert.True(t, found)
assert.Equal(t, model.AutocompleteSuggestion{Complete: "", Suggestion: "", Hint: "hint", Description: "some_help"}, suggestion)
found, _, _, suggestion = parseInputTextArgument(argument, "", " ")
assert.True(t, found)
assert.Equal(t, model.AutocompleteSuggestion{Complete: " ", Suggestion: "", Hint: "hint", Description: "some_help"}, suggestion)
found, _, _, suggestion = parseInputTextArgument(argument, "", "abc")
assert.True(t, found)
assert.Equal(t, model.AutocompleteSuggestion{Complete: "abc", Suggestion: "", Hint: "hint", Description: "some_help"}, suggestion)
found, _, _, suggestion = parseInputTextArgument(argument, "", "\"abc dfd df ")
assert.True(t, found)
assert.Equal(t, model.AutocompleteSuggestion{Complete: "\"abc dfd df ", Suggestion: "", Hint: "hint", Description: "some_help"}, suggestion)
found, parsed, toBeParsed, _ := parseInputTextArgument(argument, "", "abc efg ")
assert.False(t, found)
assert.Equal(t, "abc ", parsed)
assert.Equal(t, "efg ", toBeParsed)
found, parsed, toBeParsed, _ = parseInputTextArgument(argument, "", "abc ")
assert.False(t, found)
assert.Equal(t, "abc ", parsed)
assert.Equal(t, "", toBeParsed)
found, parsed, toBeParsed, _ = parseInputTextArgument(argument, "", "\"abc def\" abc")
assert.False(t, found)
assert.Equal(t, "\"abc def\" ", parsed)
assert.Equal(t, "abc", toBeParsed)
found, parsed, toBeParsed, _ = parseInputTextArgument(argument, "", "\"abc def\"")
assert.False(t, found)
assert.Equal(t, "\"abc def\"", parsed)
assert.Equal(t, "", toBeParsed)
}
func TestParseNamedArguments(t *testing.T) {
argument := &model.AutocompleteArg{
Name: "name", //named
HelpText: "some_help",
Type: model.AutocompleteArgTypeText,
Data: &model.AutocompleteTextArg{Hint: "hint", Pattern: "pat"},
}
found, _, _, suggestion := parseNamedArgument(argument, "", "")
assert.True(t, found)
assert.Equal(t, model.AutocompleteSuggestion{Complete: "--name ", Suggestion: "--name", Hint: "", Description: "some_help"}, suggestion)
found, _, _, suggestion = parseNamedArgument(argument, "", " ")
assert.True(t, found)
assert.Equal(t, model.AutocompleteSuggestion{Complete: " --name ", Suggestion: "--name", Hint: "", Description: "some_help"}, suggestion)
found, parsed, toBeParsed, _ := parseNamedArgument(argument, "", "abc")
assert.False(t, found)
assert.Equal(t, "abc", parsed)
assert.Equal(t, "", toBeParsed)
found, parsed, toBeParsed, suggestion = parseNamedArgument(argument, "", "-")
assert.True(t, found)
assert.Equal(t, "-", parsed)
assert.Equal(t, "", toBeParsed)
assert.Equal(t, model.AutocompleteSuggestion{Complete: "--name ", Suggestion: "--name", Hint: "", Description: "some_help"}, suggestion)
found, parsed, toBeParsed, suggestion = parseNamedArgument(argument, "", " -")
assert.True(t, found)
assert.Equal(t, " -", parsed)
assert.Equal(t, "", toBeParsed)
assert.Equal(t, model.AutocompleteSuggestion{Complete: " --name ", Suggestion: "--name", Hint: "", Description: "some_help"}, suggestion)
found, parsed, toBeParsed, suggestion = parseNamedArgument(argument, "", "--name")
assert.True(t, found)
assert.Equal(t, "--name", parsed)
assert.Equal(t, "", toBeParsed)
assert.Equal(t, model.AutocompleteSuggestion{Complete: "--name ", Suggestion: "--name", Hint: "", Description: "some_help"}, suggestion)
found, parsed, toBeParsed, _ = parseNamedArgument(argument, "", "--name bla")
assert.False(t, found)
assert.Equal(t, "--name ", parsed)
assert.Equal(t, "bla", toBeParsed)
found, parsed, toBeParsed, _ = parseNamedArgument(argument, "", "--name bla gla")
assert.False(t, found)
assert.Equal(t, "--name ", parsed)
assert.Equal(t, "bla gla", toBeParsed)
found, parsed, toBeParsed, _ = parseNamedArgument(argument, "", "--name \"bla gla\"")
assert.False(t, found)
assert.Equal(t, "--name ", parsed)
assert.Equal(t, "\"bla gla\"", toBeParsed)
found, parsed, toBeParsed, _ = parseNamedArgument(argument, "", "--name \"bla gla\" ")
assert.False(t, found)
assert.Equal(t, "--name ", parsed)
assert.Equal(t, "\"bla gla\" ", toBeParsed)
found, parsed, toBeParsed, _ = parseNamedArgument(argument, "", "bla")
assert.False(t, found)
assert.Equal(t, "bla", parsed)
assert.Equal(t, "", toBeParsed)
}
func TestSuggestions(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
jira := createJiraAutocompleteData()
suggestions := th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "ji", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, jira.Trigger, suggestions[0].Complete)
assert.Equal(t, jira.Trigger, suggestions[0].Suggestion)
assert.Equal(t, "[command]", suggestions[0].Hint)
assert.Equal(t, jira.HelpText, suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira crea", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira create", suggestions[0].Complete)
assert.Equal(t, "create", suggestions[0].Suggestion)
assert.Equal(t, "[issue text]", suggestions[0].Hint)
assert.Equal(t, "Create a new Issue", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira c", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 2)
assert.Equal(t, "jira create", suggestions[1].Complete)
assert.Equal(t, "create", suggestions[1].Suggestion)
assert.Equal(t, "[issue text]", suggestions[1].Hint)
assert.Equal(t, "Create a new Issue", suggestions[1].Description)
assert.Equal(t, "jira connect", suggestions[0].Complete)
assert.Equal(t, "connect", suggestions[0].Suggestion)
assert.Equal(t, "[url]", suggestions[0].Hint)
assert.Equal(t, "Connect your Mattermost account to your Jira account", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira create ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira create ", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "[text]", suggestions[0].Hint)
assert.Equal(t, "This text is optional, will be inserted into the description field", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira create some", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira create some", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "[text]", suggestions[0].Hint)
assert.Equal(t, "This text is optional, will be inserted into the description field", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira create some text ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 0)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "invalid command", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 0)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira settings notifications o", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 2)
assert.Equal(t, "jira settings notifications On", suggestions[0].Complete)
assert.Equal(t, "On", suggestions[0].Suggestion)
assert.Equal(t, "Turn notifications on", suggestions[0].Hint)
assert.Equal(t, "", suggestions[0].Description)
assert.Equal(t, "jira settings notifications Off", suggestions[1].Complete)
assert.Equal(t, "Off", suggestions[1].Suggestion)
assert.Equal(t, "Turn notifications off", suggestions[1].Hint)
assert.Equal(t, "", suggestions[1].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 11)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira ", model.SYSTEM_USER_ROLE_ID)
assert.Len(t, suggestions, 9)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira create \"some issue text", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira create \"some issue text", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "[text]", suggestions[0].Hint)
assert.Equal(t, "This text is optional, will be inserted into the description field", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira timezone ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira timezone --zone ", suggestions[0].Complete)
assert.Equal(t, "--zone", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "Set timezone", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira timezone --", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira timezone --zone ", suggestions[0].Complete)
assert.Equal(t, "--zone", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "Set timezone", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira timezone --zone ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira timezone --zone ", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "[UTC+07:00]", suggestions[0].Hint)
assert.Equal(t, "Set timezone", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira timezone --zone bla", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "jira timezone --zone bla", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "[UTC+07:00]", suggestions[0].Hint)
assert.Equal(t, "Set timezone", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{jira}, "", "jira timezone bla", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 0)
commandA := &model.Command{
Trigger: "alice",
AutocompleteData: model.NewAutocompleteData("alice", "", ""),
}
commandB := &model.Command{
Trigger: "bob",
AutocompleteData: model.NewAutocompleteData("bob", "", ""),
}
commandC := &model.Command{
Trigger: "charles",
AutocompleteData: model.NewAutocompleteData("charles", "", ""),
}
suggestions = th.App.GetSuggestions([]*model.Command{commandB, commandC, commandA}, "", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 3)
assert.Equal(t, "alice", suggestions[0].Complete)
assert.Equal(t, "bob", suggestions[1].Complete)
assert.Equal(t, "charles", suggestions[2].Complete)
}
func TestCommandWithOptionalArgs(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
command := createCommandWithOptionalArgs()
suggestions := th.App.getSuggestions([]*model.AutocompleteData{command}, "", "comm", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, command.Trigger, suggestions[0].Complete)
assert.Equal(t, command.Trigger, suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, command.HelpText, suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 4)
assert.Equal(t, "command subcommand1", suggestions[0].Complete)
assert.Equal(t, "subcommand1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "", suggestions[0].Description)
assert.Equal(t, "command subcommand2", suggestions[1].Complete)
assert.Equal(t, "subcommand2", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "", suggestions[1].Description)
assert.Equal(t, "command subcommand3", suggestions[2].Complete)
assert.Equal(t, "subcommand3", suggestions[2].Suggestion)
assert.Equal(t, "", suggestions[2].Hint)
assert.Equal(t, "", suggestions[2].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand1 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 2)
assert.Equal(t, "command subcommand1 item1", suggestions[0].Complete)
assert.Equal(t, "item1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "", suggestions[0].Description)
assert.Equal(t, "command subcommand1 item2", suggestions[1].Complete)
assert.Equal(t, "item2", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "", suggestions[1].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand1 item1 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "command subcommand1 item1 --name2 ", suggestions[0].Complete)
assert.Equal(t, "--name2", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg2", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand1 item1 --name2 bla", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "command subcommand1 item1 --name2 bla", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg2", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand2 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 2)
assert.Equal(t, "command subcommand2 --name1 ", suggestions[0].Complete)
assert.Equal(t, "--name1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg1", suggestions[0].Description)
assert.Equal(t, "command subcommand2 ", suggestions[1].Complete)
assert.Equal(t, "", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "arg2", suggestions[1].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand2 -", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 2)
assert.Equal(t, "command subcommand2 --name1 ", suggestions[0].Complete)
assert.Equal(t, "--name1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg1", suggestions[0].Description)
assert.Equal(t, "command subcommand2 -", suggestions[1].Complete)
assert.Equal(t, "", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "arg2", suggestions[1].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand2 --name1 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 3)
assert.Equal(t, "command subcommand2 --name1 item1", suggestions[0].Complete)
assert.Equal(t, "item1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "", suggestions[0].Description)
assert.Equal(t, "command subcommand2 --name1 item2", suggestions[1].Complete)
assert.Equal(t, "item2", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "", suggestions[1].Description)
assert.Equal(t, "command subcommand2 --name1 ", suggestions[2].Complete)
assert.Equal(t, "", suggestions[2].Suggestion)
assert.Equal(t, "", suggestions[2].Hint)
assert.Equal(t, "arg3", suggestions[2].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand2 --name1 item", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 3)
assert.Equal(t, "command subcommand2 --name1 item1", suggestions[0].Complete)
assert.Equal(t, "item1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "", suggestions[0].Description)
assert.Equal(t, "command subcommand2 --name1 item2", suggestions[1].Complete)
assert.Equal(t, "item2", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "", suggestions[1].Description)
assert.Equal(t, "command subcommand2 --name1 item", suggestions[2].Complete)
assert.Equal(t, "", suggestions[2].Suggestion)
assert.Equal(t, "", suggestions[2].Hint)
assert.Equal(t, "arg3", suggestions[2].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand2 --name1 item1 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "command subcommand2 --name1 item1 ", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg2", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand2 --name1 item1 bla ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "command subcommand2 --name1 item1 bla ", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg3", suggestions[0].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand2 --name1 item1 bla bla ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 0)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand3 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 3)
assert.Equal(t, "command subcommand3 --name1 ", suggestions[0].Complete)
assert.Equal(t, "--name1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg1", suggestions[0].Description)
assert.Equal(t, "command subcommand3 --name2 ", suggestions[1].Complete)
assert.Equal(t, "--name2", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "arg2", suggestions[1].Description)
assert.Equal(t, "command subcommand3 --name3 ", suggestions[2].Complete)
assert.Equal(t, "--name3", suggestions[2].Suggestion)
assert.Equal(t, "", suggestions[2].Hint)
assert.Equal(t, "arg3", suggestions[2].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand3 --name", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 3)
assert.Equal(t, "command subcommand3 --name1 ", suggestions[0].Complete)
assert.Equal(t, "--name1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "arg1", suggestions[0].Description)
assert.Equal(t, "command subcommand3 --name2 ", suggestions[1].Complete)
assert.Equal(t, "--name2", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "arg2", suggestions[1].Description)
assert.Equal(t, "command subcommand3 --name3 ", suggestions[2].Complete)
assert.Equal(t, "--name3", suggestions[2].Suggestion)
assert.Equal(t, "", suggestions[2].Hint)
assert.Equal(t, "arg3", suggestions[2].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand3 --name1 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 2)
assert.Equal(t, "command subcommand3 --name1 item1", suggestions[0].Complete)
assert.Equal(t, "item1", suggestions[0].Suggestion)
assert.Equal(t, "", suggestions[0].Hint)
assert.Equal(t, "", suggestions[0].Description)
assert.Equal(t, "command subcommand3 --name1 item2", suggestions[1].Complete)
assert.Equal(t, "item2", suggestions[1].Suggestion)
assert.Equal(t, "", suggestions[1].Hint)
assert.Equal(t, "", suggestions[1].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand4 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 2)
assert.Equal(t, "command subcommand4 item1", suggestions[0].Complete)
assert.Equal(t, "item1", suggestions[0].Suggestion)
assert.Equal(t, "(optional)", suggestions[0].Hint)
assert.Equal(t, "help3", suggestions[0].Description)
assert.Equal(t, "command subcommand4 ", suggestions[1].Complete)
assert.Equal(t, "", suggestions[1].Suggestion)
assert.Equal(t, "message", suggestions[1].Hint)
assert.Equal(t, "help4", suggestions[1].Description)
suggestions = th.App.getSuggestions([]*model.AutocompleteData{command}, "", "command subcommand4 item1 ", model.SYSTEM_ADMIN_ROLE_ID)
assert.Len(t, suggestions, 1)
assert.Equal(t, "command subcommand4 item1 ", suggestions[0].Complete)
assert.Equal(t, "", suggestions[0].Suggestion)
assert.Equal(t, "message", suggestions[0].Hint)
assert.Equal(t, "help4", suggestions[0].Description)
}
func createCommandWithOptionalArgs() *model.AutocompleteData {
command := model.NewAutocompleteData("command", "", "")
subCommand1 := model.NewAutocompleteData("subcommand1", "", "")
subCommand1.AddStaticListArgument("arg1", true, []model.AutocompleteListItem{{Item: "item1"}, {Item: "item2"}})
subCommand1.AddNamedTextArgument("name2", "arg2", "", "", false)
command.AddCommand(subCommand1)
subCommand2 := model.NewAutocompleteData("subcommand2", "", "")
subCommand2.AddNamedStaticListArgument("name1", "arg1", false, []model.AutocompleteListItem{{Item: "item1"}, {Item: "item2"}})
subCommand2.AddTextArgument("arg2", "", "")
subCommand2.AddTextArgument("arg3", "", "")
command.AddCommand(subCommand2)
subCommand3 := model.NewAutocompleteData("subcommand3", "", "")
subCommand3.AddNamedStaticListArgument("name1", "arg1", false, []model.AutocompleteListItem{{Item: "item1"}, {Item: "item2"}})
subCommand3.AddNamedTextArgument("name2", "arg2", "", "", false)
subCommand3.AddNamedTextArgument("name3", "arg3", "", "", false)
command.AddCommand(subCommand3)
subcommand4 := model.NewAutocompleteData("subcommand4", "", "help1")
subcommand4.AddStaticListArgument("help2", false, []model.AutocompleteListItem{{
HelpText: "help3",
Hint: "(optional)",
Item: "item1",
}})
subcommand4.AddTextArgument("help4", "message", "")
command.AddCommand(subcommand4)
return command
}
// createJiraAutocompleteData will create autocomplete data for jira plugin. For testing purposes only.
func createJiraAutocompleteData() *model.AutocompleteData {
jira := model.NewAutocompleteData("jira", "[command]", "Available commands: connect, assign, disconnect, create, transition, view, subscribe, settings, install cloud/server, uninstall cloud/server, help")
connect := model.NewAutocompleteData("connect", "[url]", "Connect your Mattermost account to your Jira account")
jira.AddCommand(connect)
disconnect := model.NewAutocompleteData("disconnect", "", "Disconnect your Mattermost account from your Jira account")
jira.AddCommand(disconnect)
assign := model.NewAutocompleteData("assign", "[issue]", "Change the assignee of a Jira issue")
assign.AddDynamicListArgument("List of issues is downloading from your Jira account", "/url/issue-key", true)
assign.AddDynamicListArgument("List of assignees is downloading from your Jira account", "/url/assignee", true)
jira.AddCommand(assign)
create := model.NewAutocompleteData("create", "[issue text]", "Create a new Issue")
create.AddTextArgument("This text is optional, will be inserted into the description field", "[text]", "")
jira.AddCommand(create)
transition := model.NewAutocompleteData("transition", "[issue]", "Change the state of a Jira issue")
assign.AddDynamicListArgument("List of issues is downloading from your Jira account", "/url/issue-key", true)
assign.AddDynamicListArgument("List of states is downloading from your Jira account", "/url/states", true)
jira.AddCommand(transition)
subscribe := model.NewAutocompleteData("subscribe", "", "Configure the Jira notifications sent to this channel")
jira.AddCommand(subscribe)
view := model.NewAutocompleteData("view", "[issue]", "View the details of a specific Jira issue")
assign.AddDynamicListArgument("List of issues is downloading from your Jira account", "/url/issue-key", true)
jira.AddCommand(view)
settings := model.NewAutocompleteData("settings", "", "Update your user settings")
notifications := model.NewAutocompleteData("notifications", "[on/off]", "Turn notifications on or off")
items := []model.AutocompleteListItem{
{
Hint: "Turn notifications on",
Item: "On",
},
{
Hint: "Turn notifications off",
Item: "Off",
},
}
notifications.AddStaticListArgument("Turn notifications on or off", true, items)
settings.AddCommand(notifications)
jira.AddCommand(settings)
timezone := model.NewAutocompleteData("timezone", "", "Update your timezone")
timezone.AddNamedTextArgument("zone", "Set timezone", "[UTC+07:00]", "", true)
jira.AddCommand(timezone)
install := model.NewAutocompleteData("install", "", "Connect Mattermost to a Jira instance")
install.RoleID = model.SYSTEM_ADMIN_ROLE_ID
cloud := model.NewAutocompleteData("cloud", "", "Connect to a Jira Cloud instance")
urlPattern := "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)"
cloud.AddTextArgument("input URL of the Jira Cloud instance", "[URL]", urlPattern)
install.AddCommand(cloud)
server := model.NewAutocompleteData("server", "", "Connect to a Jira Server or Data Center instance")
server.AddTextArgument("input URL of the Jira Server or Data Center instance", "[URL]", urlPattern)
install.AddCommand(server)
jira.AddCommand(install)
uninstall := model.NewAutocompleteData("uninstall", "", "Disconnect Mattermost from a Jira instance")
uninstall.RoleID = model.SYSTEM_ADMIN_ROLE_ID
cloud = model.NewAutocompleteData("cloud", "", "Disconnect from a Jira Cloud instance")
cloud.AddTextArgument("input URL of the Jira Cloud instance", "[URL]", urlPattern)
uninstall.AddCommand(cloud)
server = model.NewAutocompleteData("server", "", "Disconnect from a Jira Server or Data Center instance")
server.AddTextArgument("input URL of the Jira Server or Data Center instance", "[URL]", urlPattern)
uninstall.AddCommand(server)
jira.AddCommand(uninstall)
return jira
}

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

@@ -25,12 +25,15 @@ func (me *RenameProvider) GetTrigger() string {
}
func (me *RenameProvider) GetCommand(a *App, T goi18n.TranslateFunc) *model.Command {
renameAutocompleteData := model.NewAutocompleteData(CMD_RENAME, T("api.command_channel_rename.hint"), T("api.command_channel_rename.desc"))
renameAutocompleteData.AddTextArgument(T("api.command_channel_rename.hint"), "[text]", "")
return &model.Command{
Trigger: CMD_RENAME,
AutoComplete: true,
AutoCompleteDesc: T("api.command_channel_rename.desc"),
AutoCompleteHint: T("api.command_channel_rename.hint"),
DisplayName: T("api.command_channel_rename.name"),
AutocompleteData: renameAutocompleteData,
}
}

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

@@ -325,27 +325,34 @@ func (w *LocalResponseWriter) WriteHeader(statusCode int) {
w.status = statusCode
}
func (a *App) DoLocalRequest(rawURL string, body []byte) (*http.Response, *model.AppError) {
func (a *App) doPluginRequest(method, rawURL string, values url.Values, body []byte) (*http.Response, *model.AppError) {
rawURL = strings.TrimPrefix(rawURL, "/")
inURL, err := url.Parse(rawURL)
if err != nil {
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
return nil, model.NewAppError("doPluginRequest", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
}
result := strings.Split(inURL.Path, "/")
if len(result) < 2 {
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err=Unable to find pluginId", http.StatusBadRequest)
return nil, model.NewAppError("doPluginRequest", "api.post.do_action.action_integration.app_error", nil, "err=Unable to find pluginId", http.StatusBadRequest)
}
if result[0] != "plugins" {
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err=plugins not in path", http.StatusBadRequest)
return nil, model.NewAppError("doPluginRequest", "api.post.do_action.action_integration.app_error", nil, "err=plugins not in path", http.StatusBadRequest)
}
pluginId := result[1]
path := strings.TrimPrefix(inURL.Path, "plugins/"+pluginId)
w := &LocalResponseWriter{}
r, err := http.NewRequest("POST", path, bytes.NewReader(body))
base, err := url.Parse(path)
if err != nil {
return nil, model.NewAppError("DoActionRequest", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
return nil, model.NewAppError("doPluginRequest", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
}
if values != nil {
base.RawQuery = values.Encode()
}
w := &LocalResponseWriter{}
r, err := http.NewRequest(method, base.String(), bytes.NewReader(body))
if err != nil {
return nil, model.NewAppError("doPluginRequest", "api.post.do_action.action_integration.app_error", nil, "err="+err.Error(), http.StatusBadRequest)
}
r.Header.Set("Mattermost-User-Id", a.Session().UserId)
r.Header.Set(model.HEADER_AUTH, "Bearer "+a.Session().Token)
@@ -370,6 +377,10 @@ func (a *App) DoLocalRequest(rawURL string, body []byte) (*http.Response, *model
return resp, nil
}
func (a *App) DoLocalRequest(rawURL string, body []byte) (*http.Response, *model.AppError) {
return a.doPluginRequest("POST", rawURL, nil, body)
}
func (a *App) OpenInteractiveDialog(request model.OpenDialogRequest) *model.AppError {
clientTriggerId, userId, err := request.DecodeAndVerifyTriggerId(a.AsymmetricSigningKey())
if err != nil {

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

@@ -7647,6 +7647,23 @@ func (a *OpenTracingAppLayer) GetStatusesByIds(userIds []string) (map[string]int
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetSuggestions(commands []*model.Command, userInput string, roleID string) []model.AutocompleteSuggestion {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetSuggestions")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0 := a.app.GetSuggestions(commands, userInput, roleID)
return resultVar0
}
func (a *OpenTracingAppLayer) GetTeam(teamId string) (*model.Team, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetTeam")

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

@@ -4,11 +4,12 @@
package app
import (
"fmt"
"net/http"
"net/url"
"strings"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/pkg/errors"
)
type PluginCommand struct {
@@ -18,16 +19,36 @@ type PluginCommand struct {
func (a *App) RegisterPluginCommand(pluginId string, command *model.Command) error {
if command.Trigger == "" {
return fmt.Errorf("invalid command")
return errors.New("invalid command")
}
if command.AutocompleteData != nil {
if err := command.AutocompleteData.IsValid(); err != nil {
return errors.Wrap(err, "invalid autocomplete data in command")
}
}
if command.AutocompleteData == nil {
command.AutocompleteData = model.NewAutocompleteData(command.Trigger, command.AutoCompleteHint, command.AutoCompleteDesc)
} else {
baseURL, err := url.Parse("/plugins/" + pluginId)
if err != nil {
return errors.Wrapf(err, "Can't parse url %s", "/plugins/"+pluginId)
}
err = command.AutocompleteData.UpdateRelativeURLsForPluginCommands(baseURL)
if err != nil {
return errors.Wrap(err, "Can't update relative urls for plugin commands")
}
}
command = &model.Command{
Trigger: strings.ToLower(command.Trigger),
TeamId: command.TeamId,
AutoComplete: command.AutoComplete,
AutoCompleteDesc: command.AutoCompleteDesc,
AutoCompleteHint: command.AutoCompleteHint,
DisplayName: command.DisplayName,
Trigger: strings.ToLower(command.Trigger),
TeamId: command.TeamId,
AutoComplete: command.AutoComplete,
AutoCompleteDesc: command.AutoCompleteDesc,
AutoCompleteHint: command.AutoCompleteHint,
DisplayName: command.DisplayName,
AutocompleteData: command.AutocompleteData,
AutocompleteIconData: command.AutocompleteIconData,
}
a.Srv().pluginCommandsLock.Lock()