2015-10-08 12:27:09 -04:00
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
2015-06-14 23:53:32 -08:00
// See License.txt for license information.
package api
import (
2015-11-21 12:01:14 -05:00
"io"
2015-08-17 13:13:27 -07:00
"net/http"
2015-11-21 12:01:14 -05:00
"path"
2015-08-17 13:13:27 -07:00
"strconv"
"strings"
"time"
2016-01-11 09:12:51 -06:00
l4g "github.com/alecthomas/log4go"
2015-06-14 23:53:32 -08:00
"github.com/gorilla/mux"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
type commandHandler func ( c * Context , command * model . Command ) bool
2015-10-25 23:55:50 +01:00
var (
cmds = map [ string ] string {
"logoutCommand" : "/logout" ,
"joinCommand" : "/join" ,
"loadTestCommand" : "/loadtest" ,
"echoCommand" : "/echo" ,
"shrugCommand" : "/shrug" ,
2015-11-01 17:42:10 -08:00
"meCommand" : "/me" ,
2015-10-25 23:55:50 +01:00
}
commands = [ ] commandHandler {
logoutCommand ,
joinCommand ,
loadTestCommand ,
echoCommand ,
shrugCommand ,
2015-11-01 17:42:10 -08:00
meCommand ,
2015-10-25 23:55:50 +01:00
}
commandNotImplementedErr = model . NewAppError ( "checkCommand" , "Command not implemented" , "" )
)
2015-08-25 09:19:07 -07:00
var echoSem chan bool
2015-06-14 23:53:32 -08:00
func InitCommand ( r * mux . Router ) {
l4g . Debug ( "Initializing command api routes" )
r . Handle ( "/command" , ApiUserRequired ( command ) ) . Methods ( "POST" )
}
func command ( c * Context , w http . ResponseWriter , r * http . Request ) {
props := model . MapFromJson ( r . Body )
command := & model . Command {
Command : strings . TrimSpace ( props [ "command" ] ) ,
ChannelId : strings . TrimSpace ( props [ "channelId" ] ) ,
Suggest : props [ "suggest" ] == "true" ,
Suggestions : make ( [ ] * model . SuggestCommand , 0 , 128 ) ,
}
checkCommand ( c , command )
if c . Err != nil {
2015-10-25 23:55:50 +01:00
if c . Err != commandNotImplementedErr {
return
} else {
c . Err = nil
command . Response = model . RESP_NOT_IMPLEMENTED
w . Write ( [ ] byte ( command . ToJson ( ) ) )
return
}
2015-06-14 23:53:32 -08:00
} else {
w . Write ( [ ] byte ( command . ToJson ( ) ) )
}
}
func checkCommand ( c * Context , command * model . Command ) bool {
if len ( command . Command ) == 0 || strings . Index ( command . Command , "/" ) != 0 {
c . Err = model . NewAppError ( "checkCommand" , "Command must start with /" , "" )
return false
}
if len ( command . ChannelId ) > 0 {
2016-01-20 13:36:16 -06:00
cchan := Srv . Store . Channel ( ) . CheckPermissionsTo ( c . Session . TeamId , command . ChannelId , c . Session . UserId )
2015-06-14 23:53:32 -08:00
if ! c . HasPermissionsToChannel ( cchan , "checkCommand" ) {
return true
}
}
2015-10-25 23:55:50 +01:00
if ! command . Suggest {
implemented := false
for _ , cmd := range cmds {
bounds := len ( cmd )
if len ( command . Command ) < bounds {
continue
}
if command . Command [ : bounds ] == cmd {
implemented = true
}
}
if ! implemented {
c . Err = commandNotImplementedErr
return false
}
}
2015-06-14 23:53:32 -08:00
for _ , v := range commands {
2015-06-17 12:07:35 -04:00
2015-08-17 13:13:27 -07:00
if v ( c , command ) || c . Err != nil {
2015-06-14 23:53:32 -08:00
return true
}
}
return false
}
func logoutCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd := cmds [ "logoutCommand" ]
2015-06-14 23:53:32 -08:00
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 echoCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd := cmds [ "echoCommand" ]
2015-08-25 09:19:07 -07:00
maxThreads := 100
2015-06-14 23:53:32 -08:00
2015-08-17 13:13:27 -07:00
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
2015-06-14 23:53:32 -08:00
}
2015-08-17 13:13:27 -07:00
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 ]
}
2015-06-14 23:53:32 -08:00
}
2015-08-25 09:19:07 -07:00
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
2015-08-17 13:13:27 -07:00
go func ( ) {
2015-08-25 09:19:07 -07:00
defer func ( ) { <- echoSem } ( )
2015-08-17 13:13:27 -07:00
post := & model . Post { }
post . ChannelId = command . ChannelId
post . Message = message
2015-06-14 23:53:32 -08:00
2015-08-17 13:13:27 -07:00
time . Sleep ( time . Duration ( delay ) * time . Second )
2015-10-01 14:07:20 -04:00
if _ , err := CreatePost ( c , post , true ) ; err != nil {
2015-08-17 13:13:27 -07:00
l4g . Error ( "Unable to create /echo post, err=%v" , err )
2015-06-14 23:53:32 -08:00
}
2015-08-17 13:13:27 -07:00
} ( )
command . Response = model . RESP_EXECUTED
return true
2015-06-14 23:53:32 -08:00
} else if strings . Index ( cmd , command . Command ) == 0 {
2015-09-02 17:06:22 -07:00
command . AddSuggestion ( & model . SuggestCommand { Suggestion : cmd , Description : "Echo back text from your account, /echo \"message\" [delay in seconds]" } )
2015-06-14 23:53:32 -08:00
}
return false
}
2015-11-01 17:42:10 -08:00
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
}
2015-10-16 15:13:29 -05:00
func shrugCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd := cmds [ "shrugCommand" ]
2015-10-16 15:13:29 -05:00
if ! command . Suggest && strings . Index ( command . Command , cmd ) == 0 {
2015-10-25 18:37:48 +01:00
message := ` ¯\\\_(ツ)_/¯ `
2015-10-16 15:13:29 -05:00
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
}
2015-06-14 23:53:32 -08:00
func joinCommand ( c * Context , command * model . Command ) bool {
// looks for "/join channel-name"
2015-10-25 23:55:50 +01:00
cmd := cmds [ "joinCommand" ]
2015-06-14 23:53:32 -08:00
if strings . Index ( command . Command , cmd ) == 0 {
parts := strings . Split ( command . Command , " " )
startsWith := ""
if len ( parts ) == 2 {
startsWith = parts [ 1 ]
}
2016-01-20 13:36:16 -06:00
if result := <- Srv . Store . Channel ( ) . GetMoreChannels ( c . Session . TeamId , c . Session . UserId ) ; result . Err != nil {
2015-06-14 23:53:32 -08:00
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
}
2015-06-29 10:24:45 -04:00
JoinChannel ( c , v . Id , "" )
2015-06-14 23:53:32 -08:00
if c . Err != nil {
return false
}
2015-09-29 11:48:13 -05:00
command . GotoLocation = c . GetTeamURL ( ) + "/channels/" + v . Name
2015-06-14 23:53:32 -08:00
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 loadTestCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd := cmds [ "loadTestCommand" ]
2015-06-14 23:53:32 -08:00
2015-09-22 12:12:50 -07:00
// This command is only available when EnableTesting is true
if ! utils . Cfg . ServiceSettings . EnableTesting {
2015-06-14 23:53:32 -08:00
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
}
2015-11-21 12:01:14 -05:00
if loadTestUrlCommand ( c , command ) {
return true
}
2015-06-14 23:53:32 -08:00
} else if strings . Index ( cmd , command . Command ) == 0 {
command . AddSuggestion ( & model . SuggestCommand { Suggestion : cmd , Description : "Debug Load Testing" } )
}
return false
}
func parseRange ( command string , cmd string ) ( utils . Range , bool ) {
tokens := strings . Fields ( strings . TrimPrefix ( command , cmd ) )
var begin int
var end int
var err1 error
var err2 error
switch {
case len ( tokens ) == 1 :
begin , err1 = strconv . Atoi ( tokens [ 0 ] )
end = begin
if err1 != nil {
return utils . Range { 0 , 0 } , false
}
case len ( tokens ) >= 2 :
begin , err1 = strconv . Atoi ( tokens [ 0 ] )
end , err2 = strconv . Atoi ( tokens [ 1 ] )
if err1 != nil || err2 != nil {
return utils . Range { 0 , 0 } , false
}
default :
return utils . Range { 0 , 0 } , false
}
return utils . Range { begin , end } , true
}
func contains ( items [ ] string , token string ) bool {
for _ , elem := range items {
if elem == token {
return true
}
}
return false
}
func loadTestSetupCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd := cmds [ "loadTestCommand" ] + " setup"
2015-06-14 23:53:32 -08:00
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 ] )
}
}
2015-09-16 15:49:12 -04:00
client := model . NewClient ( c . GetSiteURL ( ) )
2015-06-14 23:53:32 -08:00
if doTeams {
if err := CreateBasicUser ( client ) ; err != nil {
2015-10-30 12:42:26 -05:00
l4g . Error ( "Failed to create testing environment" )
2015-06-14 23:53:32 -08:00
return true
}
2015-07-08 11:50:10 -04:00
client . LoginByEmail ( BTEST_TEAM_NAME , BTEST_USER_EMAIL , BTEST_USER_PASSWORD )
2015-10-30 12:42:26 -05:00
environment , err := CreateTestEnvironmentWithTeams (
2015-06-14 23:53:32 -08:00
client ,
utils . Range { numTeams , numTeams } ,
utils . Range { numChannels , numChannels } ,
utils . Range { numUsers , numUsers } ,
utils . Range { numPosts , numPosts } ,
doFuzz )
if err != true {
2015-10-30 12:42:26 -05:00
l4g . Error ( "Failed to create testing environment" )
2015-06-14 23:53:32 -08:00
return true
} else {
2015-10-30 12:42:26 -05:00
l4g . Info ( "Testing environment created" )
for i := 0 ; i < len ( environment . Teams ) ; i ++ {
l4g . Info ( "Team Created: " + environment . Teams [ i ] . Name )
l4g . Info ( "\t User to login: " + environment . Environments [ i ] . Users [ 0 ] . Email + ", " + USER_PASSWORD )
2015-06-14 23:53:32 -08:00
}
}
} else {
2015-09-18 12:16:53 -04:00
client . MockSession ( c . Session . Token )
2015-10-30 12:42:26 -05:00
CreateTestEnvironmentInTeam (
2015-06-14 23:53:32 -08:00
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 ,
2015-10-30 12:42:26 -05:00
Description : "Creates a testing environment in current team. [teams] [fuzz] <Num Channels> <Num Users> <NumPosts>" } )
2015-06-14 23:53:32 -08:00
}
return false
}
func loadTestUsersCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd1 := cmds [ "loadTestCommand" ] + " users"
cmd2 := cmds [ "loadTestCommand" ] + " users fuzz"
2015-06-14 23:53:32 -08:00
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 }
}
2015-09-16 15:49:12 -04:00
client := model . NewClient ( c . GetSiteURL ( ) )
2015-06-14 23:53:32 -08:00
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 loadTestChannelsCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd1 := cmds [ "loadTestCommand" ] + " channels"
cmd2 := cmds [ "loadTestCommand" ] + " channels fuzz"
2015-06-14 23:53:32 -08:00
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 }
}
2015-09-16 15:49:12 -04:00
client := model . NewClient ( c . GetSiteURL ( ) )
2015-09-18 12:16:53 -04:00
client . MockSession ( c . Session . Token )
2015-06-14 23:53:32 -08:00
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 loadTestPostsCommand ( c * Context , command * model . Command ) bool {
2015-10-25 23:55:50 +01:00
cmd1 := cmds [ "loadTestCommand" ] + " posts"
cmd2 := cmds [ "loadTestCommand" ] + " posts fuzz"
2015-06-14 23:53:32 -08:00
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
2016-01-20 13:36:16 -06:00
if result := <- Srv . Store . User ( ) . GetProfiles ( c . Session . TeamId ) ; result . Err == nil {
2015-06-14 23:53:32 -08:00
profileUsers := result . Data . ( map [ string ] * model . User )
usernames = make ( [ ] string , len ( profileUsers ) )
i := 0
for _ , userprof := range profileUsers {
usernames [ i ] = userprof . Username
i ++
}
}
2015-09-16 15:49:12 -04:00
client := model . NewClient ( c . GetSiteURL ( ) )
2015-09-18 12:16:53 -04:00
client . MockSession ( c . Session . Token )
2015-06-14 23:53:32 -08:00
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
}
2015-11-21 12:01:14 -05:00
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
}