github.com/nhannv/mattermost-server@v5.11.1+incompatible/app/command_echo.go (about) 1 // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "fmt" 8 "strconv" 9 "strings" 10 "time" 11 12 "github.com/mattermost/mattermost-server/mlog" 13 "github.com/mattermost/mattermost-server/model" 14 goi18n "github.com/nicksnyder/go-i18n/i18n" 15 ) 16 17 var echoSem chan bool 18 19 type EchoProvider struct { 20 } 21 22 const ( 23 CMD_ECHO = "echo" 24 ) 25 26 func init() { 27 RegisterCommandProvider(&EchoProvider{}) 28 } 29 30 func (me *EchoProvider) GetTrigger() string { 31 return CMD_ECHO 32 } 33 34 func (me *EchoProvider) GetCommand(a *App, T goi18n.TranslateFunc) *model.Command { 35 return &model.Command{ 36 Trigger: CMD_ECHO, 37 AutoComplete: true, 38 AutoCompleteDesc: T("api.command_echo.desc"), 39 AutoCompleteHint: T("api.command_echo.hint"), 40 DisplayName: T("api.command_echo.name"), 41 } 42 } 43 44 func (me *EchoProvider) DoCommand(a *App, args *model.CommandArgs, message string) *model.CommandResponse { 45 if len(message) == 0 { 46 return &model.CommandResponse{Text: args.T("api.command_echo.message.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} 47 } 48 49 maxThreads := 100 50 51 delay := 0 52 if endMsg := strings.LastIndex(message, "\""); string(message[0]) == "\"" && endMsg > 1 { 53 if checkDelay, err := strconv.Atoi(strings.Trim(message[endMsg:], " \"")); err == nil { 54 delay = checkDelay 55 } 56 message = message[1:endMsg] 57 } else if strings.Contains(message, " ") { 58 delayIdx := strings.LastIndex(message, " ") 59 delayStr := strings.Trim(message[delayIdx:], " ") 60 61 if checkDelay, err := strconv.Atoi(delayStr); err == nil { 62 delay = checkDelay 63 message = message[:delayIdx] 64 } 65 } 66 67 if delay > 10000 { 68 return &model.CommandResponse{Text: args.T("api.command_echo.delay.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} 69 } 70 71 if echoSem == nil { 72 // We want one additional thread allowed so we never reach channel lockup 73 echoSem = make(chan bool, maxThreads+1) 74 } 75 76 if len(echoSem) >= maxThreads { 77 return &model.CommandResponse{Text: args.T("api.command_echo.high_volume.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} 78 } 79 80 echoSem <- true 81 a.Srv.Go(func() { 82 defer func() { <-echoSem }() 83 post := &model.Post{} 84 post.ChannelId = args.ChannelId 85 post.RootId = args.RootId 86 post.ParentId = args.ParentId 87 post.Message = message 88 post.UserId = args.UserId 89 90 time.Sleep(time.Duration(delay) * time.Second) 91 92 if _, err := a.CreatePostMissingChannel(post, true); err != nil { 93 mlog.Error(fmt.Sprintf("Unable to create /echo post, err=%v", err)) 94 } 95 }) 96 97 return &model.CommandResponse{} 98 }