func shrugCommand(c *Context, command *model.Command) bool { cmd := cmds["shrugCommand"] if !command.Suggest && strings.Index(command.Command, cmd) == 0 { message := `¯\\\_(ツ)_/¯` parameters := strings.SplitN(command.Command, " ", 2) if len(parameters) > 1 { message += " " + parameters[1] } post := &model.Post{} post.Message = message post.ChannelId = command.ChannelId if _, err := CreatePost(c, post, false); err != nil { l4g.Error(utils.T("api.command.shrug_command.create.error"), err) return false } command.Response = model.RESP_EXECUTED return true } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: c.T("api.command.shrug_command.description")}) } return false }
func meCommand(c *Context, command *model.Command) bool { cmd := cmds["meCommand"] if !command.Suggest && strings.Index(command.Command, cmd) == 0 { message := "" parameters := strings.SplitN(command.Command, " ", 2) if len(parameters) > 1 { message += "*" + parameters[1] + "*" } post := &model.Post{} post.Message = message post.ChannelId = command.ChannelId if _, err := CreatePost(c, post, false); err != nil { l4g.Error("Unable to create /me post post, err=%v", err) return false } command.Response = model.RESP_EXECUTED return true } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Do an action, /me [message]"}) } return false }
func (s SqlCommandStore) Save(command *model.Command) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} if len(command.Id) > 0 { result.Err = model.NewLocAppError("SqlCommandStore.Save", "store.sql_command.save.saving_overwrite.app_error", nil, "id="+command.Id) storeChannel <- result close(storeChannel) return } command.PreSave() if result.Err = command.IsValid(); result.Err != nil { storeChannel <- result close(storeChannel) return } if err := s.GetMaster().Insert(command); err != nil { result.Err = model.NewLocAppError("SqlCommandStore.Save", "store.sql_command.save.saving.app_error", nil, "id="+command.Id+", "+err.Error()) } else { result.Data = command } storeChannel <- result close(storeChannel) }() return storeChannel }
func loadTestCommand(c *Context, command *model.Command) bool { cmd := "/loadtest" // This command is only available when EnableTesting is true if !utils.Cfg.ServiceSettings.EnableTesting { return false } if strings.Index(command.Command, cmd) == 0 { if loadTestSetupCommand(c, command) { return true } if loadTestUsersCommand(c, command) { return true } if loadTestChannelsCommand(c, command) { return true } if loadTestPostsCommand(c, command) { return true } } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Debug Load Testing"}) } return false }
func loadTestCommand(c *Context, command *model.Command) bool { cmd := cmds["loadTestCommand"] // This command is only available when EnableTesting is true if !utils.Cfg.ServiceSettings.EnableTesting { return false } if strings.Index(command.Command, cmd) == 0 { if loadTestSetupCommand(c, command) { return true } if loadTestUsersCommand(c, command) { return true } if loadTestChannelsCommand(c, command) { return true } if loadTestPostsCommand(c, command) { return true } if loadTestUrlCommand(c, command) { return true } } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: c.T("api.command.load_test_command.description")}) } return false }
func shrugCommand(c *Context, command *model.Command) bool { cmd := "/shrug" if !command.Suggest && strings.Index(command.Command, cmd) == 0 { message := "¯\\_(ツ)_/¯" parameters := strings.SplitN(command.Command, " ", 2) if len(parameters) > 1 { message += " " + parameters[1] } post := &model.Post{} post.Message = message post.ChannelId = command.ChannelId if _, err := CreatePost(c, post, false); err != nil { l4g.Error("Unable to create /shrug post post, err=%v", err) return false } command.Response = model.RESP_EXECUTED return true } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Adds ¯\\_(ツ)_/¯ to your message, /shrug [message]"}) } return false }
func echoCommand(c *Context, command *model.Command) bool { cmd := "/echo" if strings.Index(command.Command, cmd) == 0 { parts := strings.SplitN(command.Command, " ", 3) channelName := "" if len(parts) >= 2 { channelName = parts[1] } message := "" if len(parts) >= 3 { message = parts[2] } if result := <-Srv.Store.Channel().GetChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { c.Err = result.Err return false } else { channels := result.Data.(*model.ChannelList) for _, v := range channels.Channels { if v.Type == model.CHANNEL_DIRECT { continue } if v.Name == channelName && !command.Suggest { post := &model.Post{} post.ChannelId = v.Id post.Message = message if _, err := CreateValetPost(c, post); err != nil { c.Err = err return false } command.Response = model.RESP_EXECUTED return true } if len(channelName) == 0 || (strings.Index(v.Name, channelName) == 0 && len(parts) < 3) { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd + " " + v.Name, Description: "Echo a message using Valet in a channel"}) } } } } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Echo a message using Valet in a channel"}) } return false }
func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) { if !*utils.Cfg.ServiceSettings.EnableCommands { c.Err = model.NewLocAppError("regenCommandToken", "api.command.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } if *utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations { if !(c.IsSystemAdmin() || c.IsTeamAdmin()) { c.Err = model.NewLocAppError("regenCommandToken", "api.command.admin_only.app_error", nil, "") c.Err.StatusCode = http.StatusForbidden return } } c.LogAudit("attempt") props := model.MapFromJson(r.Body) id := props["id"] if len(id) == 0 { c.SetInvalidParam("regenCommandToken", "id") return } var cmd *model.Command if result := <-Srv.Store.Command().Get(id); result.Err != nil { c.Err = result.Err return } else { cmd = result.Data.(*model.Command) if c.Session.TeamId != cmd.TeamId || (c.Session.UserId != cmd.CreatorId && !c.IsTeamAdmin()) { c.LogAudit("fail - inappropriate permissions") c.Err = model.NewLocAppError("regenToken", "api.command.regen.app_error", nil, "user_id="+c.Session.UserId) return } } cmd.Token = model.NewId() if result := <-Srv.Store.Command().Update(cmd); result.Err != nil { c.Err = result.Err return } else { w.Write([]byte(result.Data.(*model.Command).ToJson())) } }
func TestCommandStoreSave(t *testing.T) { Setup() o1 := model.Command{} o1.CreatorId = model.NewId() o1.Method = model.COMMAND_METHOD_POST o1.TeamId = model.NewId() o1.URL = "http://nowhere.com/" if err := (<-store.Command().Save(&o1)).Err; err != nil { t.Fatal("couldn't save item", err) } if err := (<-store.Command().Save(&o1)).Err; err == nil { t.Fatal("shouldn't be able to update from save") } }
func loadTestChannelsCommand(c *Context, command *model.Command) bool { cmd1 := "/loadtest channels" cmd2 := "/loadtest channels fuzz" if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { cmd := cmd1 doFuzz := false if strings.Index(command.Command, cmd2) == 0 { doFuzz = true cmd = cmd2 } channelsr, err := parseRange(command.Command, cmd) if err == false { channelsr = utils.Range{20, 30} } client := model.NewClient(c.GetSiteURL()) client.MockSession(c.Session.Token) channelCreator := NewAutoChannelCreator(client, c.Session.TeamId) channelCreator.Fuzzy = doFuzz channelCreator.CreateTestChannels(channelsr) return true } else if strings.Index(cmd1, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: "Add a specified number of random channels to current team <MinChannels> <MaxChannels>"}) command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random channels with fuzz text to current team <Min Channels> <Max Channels>"}) } else if strings.Index(cmd2, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random channels with fuzz text to current team <Min Channels> <Max Channels>"}) } return false }
func loadTestUsersCommand(c *Context, command *model.Command) bool { cmd1 := "/loadtest users" cmd2 := "/loadtest users fuzz" if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { cmd := cmd1 doFuzz := false if strings.Index(command.Command, cmd2) == 0 { doFuzz = true cmd = cmd2 } usersr, err := parseRange(command.Command, cmd) if err == false { usersr = utils.Range{10, 15} } client := model.NewClient(c.GetSiteURL()) userCreator := NewAutoUserCreator(client, c.Session.TeamId) userCreator.Fuzzy = doFuzz userCreator.CreateTestUsers(usersr) return true } else if strings.Index(cmd1, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: "Add a specified number of random users to current team <Min Users> <Max Users>"}) command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random users with fuzz text to current team <Min Users> <Max Users>"}) } else if strings.Index(cmd2, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add a specified number of random users with fuzz text to current team <Min Users> <Max Users>"}) } return false }
func loadTestUsersCommand(c *Context, command *model.Command) bool { cmd1 := cmds["loadTestCommand"] + " users" cmd2 := cmds["loadTestCommand"] + " users fuzz" if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { cmd := cmd1 doFuzz := false if strings.Index(command.Command, cmd2) == 0 { doFuzz = true cmd = cmd2 } usersr, err := parseRange(command.Command, cmd) if err == false { usersr = utils.Range{10, 15} } client := model.NewClient(c.GetSiteURL()) userCreator := NewAutoUserCreator(client, c.Session.TeamId) userCreator.Fuzzy = doFuzz userCreator.CreateTestUsers(usersr) return true } else if strings.Index(cmd1, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: c.T("api.command.load_test_users_command.users.description")}) command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: c.T("api.command.load_test_users_command.fuzz.description")}) } else if strings.Index(cmd2, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: c.T("api.command.load_test_users_command.fuzz.description")}) } return false }
func loadTestChannelsCommand(c *Context, command *model.Command) bool { cmd1 := cmds["loadTestCommand"] + " channels" cmd2 := cmds["loadTestCommand"] + " channels fuzz" if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { cmd := cmd1 doFuzz := false if strings.Index(command.Command, cmd2) == 0 { doFuzz = true cmd = cmd2 } channelsr, err := parseRange(command.Command, cmd) if err == false { channelsr = utils.Range{20, 30} } client := model.NewClient(c.GetSiteURL()) client.MockSession(c.Session.Token) channelCreator := NewAutoChannelCreator(client, c.Session.TeamId) channelCreator.Fuzzy = doFuzz channelCreator.CreateTestChannels(channelsr) return true } else if strings.Index(cmd1, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: c.T("api.command.load_test_channels_command.channel.description")}) command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: c.T("api.command.load_test_channels_command.fuzz.description")}) } else if strings.Index(cmd2, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: c.T("api.command.load_test_channels_command.fuzz.description")}) } return false }
func loadTestPostsCommand(c *Context, command *model.Command) bool { cmd1 := "/loadtest posts" cmd2 := "/loadtest posts fuzz" if strings.Index(command.Command, cmd1) == 0 && !command.Suggest { cmd := cmd1 doFuzz := false if strings.Index(command.Command, cmd2) == 0 { cmd = cmd2 doFuzz = true } postsr, err := parseRange(command.Command, cmd) if err == false { postsr = utils.Range{20, 30} } tokens := strings.Fields(strings.TrimPrefix(command.Command, cmd)) rimages := utils.Range{0, 0} if len(tokens) >= 3 { if numImages, err := strconv.Atoi(tokens[2]); err == nil { rimages = utils.Range{numImages, numImages} } } var usernames []string if result := <-Srv.Store.User().GetProfiles(c.Session.TeamId); result.Err == nil { profileUsers := result.Data.(map[string]*model.User) usernames = make([]string, len(profileUsers)) i := 0 for _, userprof := range profileUsers { usernames[i] = userprof.Username i++ } } client := model.NewClient(c.GetSiteURL()) client.MockSession(c.Session.Token) testPoster := NewAutoPostCreator(client, command.ChannelId) testPoster.Fuzzy = doFuzz testPoster.Users = usernames numImages := utils.RandIntFromRange(rimages) numPosts := utils.RandIntFromRange(postsr) for i := 0; i < numPosts; i++ { testPoster.HasImage = (i < numImages) testPoster.CreateRandomPost() } return true } else if strings.Index(cmd1, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd1, Description: "Add some random posts to current channel <Min Posts> <Max Posts> <Min Images> <Max Images>"}) command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add some random posts with fuzz text to current channel <Min Posts> <Max Posts> <Min Images> <Max Images>"}) } else if strings.Index(cmd2, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd2, Description: "Add some random posts with fuzz text to current channel <Min Posts> <Max Posts> <Min Images> <Max Images>"}) } return false }
func joinCommand(c *Context, command *model.Command) bool { // looks for "/join channel-name" cmd := "/join" if strings.Index(command.Command, cmd) == 0 { parts := strings.Split(command.Command, " ") startsWith := "" if len(parts) == 2 { startsWith = parts[1] } if result := <-Srv.Store.Channel().GetMoreChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { c.Err = result.Err return false } else { channels := result.Data.(*model.ChannelList) for _, v := range channels.Channels { if v.Name == startsWith && !command.Suggest { if v.Type == model.CHANNEL_DIRECT { return false } JoinChannel(c, v.Id, "") if c.Err != nil { return false } command.GotoLocation = c.GetTeamURL() + "/channels/" + v.Name command.Response = model.RESP_EXECUTED return true } if len(startsWith) == 0 || strings.Index(v.Name, startsWith) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd + " " + v.Name, Description: "Join the open channel"}) } } } } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Join an open channel"}) } return false }
func (s SqlCommandStore) Update(cmd *model.Command) StoreChannel { storeChannel := make(StoreChannel) go func() { result := StoreResult{} cmd.UpdateAt = model.GetMillis() if _, err := s.GetMaster().Update(cmd); err != nil { result.Err = model.NewLocAppError("SqlCommandStore.Update", "store.sql_command.save.update.app_error", nil, "id="+cmd.Id+", "+err.Error()) } else { result.Data = cmd } storeChannel <- result close(storeChannel) }() return storeChannel }
func logoutCommand(c *Context, command *model.Command) bool { cmd := "/logout" if strings.Index(command.Command, cmd) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Logout"}) if !command.Suggest { command.GotoLocation = "/logout" command.Response = model.RESP_EXECUTED return true } } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Logout"}) } return false }
func loadTestSetupCommand(c *Context, command *model.Command) bool { cmd := "/loadtest setup" if strings.Index(command.Command, cmd) == 0 && !command.Suggest { tokens := strings.Fields(strings.TrimPrefix(command.Command, cmd)) doTeams := contains(tokens, "teams") doFuzz := contains(tokens, "fuzz") numArgs := 0 if doTeams { numArgs++ } if doFuzz { numArgs++ } var numTeams int var numChannels int var numUsers int var numPosts int // Defaults numTeams = 10 numChannels = 10 numUsers = 10 numPosts = 10 if doTeams { if (len(tokens) - numArgs) >= 4 { numTeams, _ = strconv.Atoi(tokens[numArgs+0]) numChannels, _ = strconv.Atoi(tokens[numArgs+1]) numUsers, _ = strconv.Atoi(tokens[numArgs+2]) numPosts, _ = strconv.Atoi(tokens[numArgs+3]) } } else { if (len(tokens) - numArgs) >= 3 { numChannels, _ = strconv.Atoi(tokens[numArgs+0]) numUsers, _ = strconv.Atoi(tokens[numArgs+1]) numPosts, _ = strconv.Atoi(tokens[numArgs+2]) } } client := model.NewClient(c.GetSiteURL()) if doTeams { if err := CreateBasicUser(client); err != nil { l4g.Error("Failed to create testing enviroment") return true } client.LoginByEmail(BTEST_TEAM_NAME, BTEST_USER_EMAIL, BTEST_USER_PASSWORD) enviroment, err := CreateTestEnviromentWithTeams( client, utils.Range{numTeams, numTeams}, utils.Range{numChannels, numChannels}, utils.Range{numUsers, numUsers}, utils.Range{numPosts, numPosts}, doFuzz) if err != true { l4g.Error("Failed to create testing enviroment") return true } else { l4g.Info("Testing enviroment created") for i := 0; i < len(enviroment.Teams); i++ { l4g.Info("Team Created: " + enviroment.Teams[i].Name) l4g.Info("\t User to login: "******", " + USER_PASSWORD) } } } else { client.MockSession(c.Session.Token) CreateTestEnviromentInTeam( client, c.Session.TeamId, utils.Range{numChannels, numChannels}, utils.Range{numUsers, numUsers}, utils.Range{numPosts, numPosts}, doFuzz) } return true } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{ Suggestion: cmd, Description: "Creates a testing enviroment in current team. [teams] [fuzz] <Num Channels> <Num Users> <NumPosts>"}) } return false }
func loadTestUrlCommand(c *Context, command *model.Command) bool { cmd := cmds["loadTestCommand"] + " url" if strings.Index(command.Command, cmd) == 0 && !command.Suggest { url := "" parameters := strings.SplitN(command.Command, " ", 3) if len(parameters) != 3 { c.Err = model.NewAppError("loadTestUrlCommand", "Command must contain a url", "") return true } else { url = parameters[2] } // provide a shortcut to easily access tests stored in doc/developer/tests if !strings.HasPrefix(url, "http") { url = "https://raw.githubusercontent.com/mattermost/platform/master/doc/developer/tests/" + url if path.Ext(url) == "" { url += ".md" } } var contents io.ReadCloser if r, err := http.Get(url); err != nil { c.Err = model.NewAppError("loadTestUrlCommand", "Unable to get file", err.Error()) return false } else if r.StatusCode > 400 { c.Err = model.NewAppError("loadTestUrlCommand", "Unable to get file", r.Status) return false } else { contents = r.Body } bytes := make([]byte, 4000) // break contents into 4000 byte posts for { length, err := contents.Read(bytes) if err != nil && err != io.EOF { c.Err = model.NewAppError("loadTestUrlCommand", "Encountered error reading file", err.Error()) return false } if length == 0 { break } post := &model.Post{} post.Message = string(bytes[:length]) post.ChannelId = command.ChannelId if _, err := CreatePost(c, post, false); err != nil { l4g.Error("Unable to create post, err=%v", err) return false } } command.Response = model.RESP_EXECUTED return true } else if strings.Index(cmd, command.Command) == 0 && strings.Index(command.Command, "/loadtest posts") != 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Add a post containing the text from a given url to current channel <Url>"}) } return false }
func echoCommand(c *Context, command *model.Command) bool { cmd := "/echo" maxThreads := 100 if !command.Suggest && strings.Index(command.Command, cmd) == 0 { parameters := strings.SplitN(command.Command, " ", 2) if len(parameters) != 2 || len(parameters[1]) == 0 { return false } message := strings.Trim(parameters[1], " ") delay := 0 if endMsg := strings.LastIndex(message, "\""); string(message[0]) == "\"" && endMsg > 1 { if checkDelay, err := strconv.Atoi(strings.Trim(message[endMsg:], " \"")); err == nil { delay = checkDelay } message = message[1:endMsg] } else if strings.Index(message, " ") > -1 { delayIdx := strings.LastIndex(message, " ") delayStr := strings.Trim(message[delayIdx:], " ") if checkDelay, err := strconv.Atoi(delayStr); err == nil { delay = checkDelay message = message[:delayIdx] } } if delay > 10000 { c.Err = model.NewAppError("echoCommand", "Delays must be under 10000 seconds", "") return false } if echoSem == nil { // We want one additional thread allowed so we never reach channel lockup echoSem = make(chan bool, maxThreads+1) } if len(echoSem) >= maxThreads { c.Err = model.NewAppError("echoCommand", "High volume of echo request, cannot process request", "") return false } echoSem <- true go func() { defer func() { <-echoSem }() post := &model.Post{} post.ChannelId = command.ChannelId post.Message = message time.Sleep(time.Duration(delay) * time.Second) if _, err := CreatePost(c, post, false); err != nil { l4g.Error("Unable to create /echo post, err=%v", err) } }() command.Response = model.RESP_EXECUTED return true } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Echo back text from your account, /echo \"message\" [delay in seconds]"}) } return false }
func echoCommand(c *Context, command *model.Command) bool { cmd := cmds["echoCommand"] maxThreads := 100 if !command.Suggest && strings.Index(command.Command, cmd) == 0 { parameters := strings.SplitN(command.Command, " ", 2) if len(parameters) != 2 || len(parameters[1]) == 0 { return false } message := strings.Trim(parameters[1], " ") delay := 0 if endMsg := strings.LastIndex(message, "\""); string(message[0]) == "\"" && endMsg > 1 { if checkDelay, err := strconv.Atoi(strings.Trim(message[endMsg:], " \"")); err == nil { delay = checkDelay } message = message[1:endMsg] } else if strings.Index(message, " ") > -1 { delayIdx := strings.LastIndex(message, " ") delayStr := strings.Trim(message[delayIdx:], " ") if checkDelay, err := strconv.Atoi(delayStr); err == nil { delay = checkDelay message = message[:delayIdx] } } if delay > 10000 { c.Err = model.NewLocAppError("echoCommand", "api.command.echo_command.under.app_error", nil, "") return false } if echoSem == nil { // We want one additional thread allowed so we never reach channel lockup echoSem = make(chan bool, maxThreads+1) } if len(echoSem) >= maxThreads { c.Err = model.NewLocAppError("echoCommand", "api.command.echo_command.high_volume.app_error", nil, "") return false } echoSem <- true go func() { defer func() { <-echoSem }() post := &model.Post{} post.ChannelId = command.ChannelId post.Message = message time.Sleep(time.Duration(delay) * time.Second) if _, err := CreatePost(c, post, true); err != nil { l4g.Error(utils.T("api.command.echo_command.create.error"), err) } }() command.Response = model.RESP_EXECUTED return true } else if strings.Index(cmd, command.Command) == 0 { command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: c.T("api.command.echo_command.description")}) } return false }