Merge pull request #1179 from florianorben/issue-827
Mattermost can not send message start with slash
Этот коммит содержится в:
@@ -17,14 +17,23 @@ import (
|
|||||||
|
|
||||||
type commandHandler func(c *Context, command *model.Command) bool
|
type commandHandler func(c *Context, command *model.Command) bool
|
||||||
|
|
||||||
var commands = []commandHandler{
|
var (
|
||||||
logoutCommand,
|
cmds = map[string]string{
|
||||||
joinCommand,
|
"logoutCommand": "/logout",
|
||||||
loadTestCommand,
|
"joinCommand": "/join",
|
||||||
echoCommand,
|
"loadTestCommand": "/loadtest",
|
||||||
shrugCommand,
|
"echoCommand": "/echo",
|
||||||
}
|
"shrugCommand": "/shrug",
|
||||||
|
}
|
||||||
|
commands = []commandHandler{
|
||||||
|
logoutCommand,
|
||||||
|
joinCommand,
|
||||||
|
loadTestCommand,
|
||||||
|
echoCommand,
|
||||||
|
shrugCommand,
|
||||||
|
}
|
||||||
|
commandNotImplementedErr = model.NewAppError("checkCommand", "Command not implemented", "")
|
||||||
|
)
|
||||||
var echoSem chan bool
|
var echoSem chan bool
|
||||||
|
|
||||||
func InitCommand(r *mux.Router) {
|
func InitCommand(r *mux.Router) {
|
||||||
@@ -45,7 +54,14 @@ func command(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
checkCommand(c, command)
|
checkCommand(c, command)
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
if c.Err != commandNotImplementedErr {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
c.Err = nil
|
||||||
|
command.Response = model.RESP_NOT_IMPLEMENTED
|
||||||
|
w.Write([]byte(command.ToJson()))
|
||||||
|
return
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.Write([]byte(command.ToJson()))
|
w.Write([]byte(command.ToJson()))
|
||||||
}
|
}
|
||||||
@@ -66,6 +82,23 @@ func checkCommand(c *Context, command *model.Command) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, v := range commands {
|
for _, v := range commands {
|
||||||
|
|
||||||
if v(c, command) || c.Err != nil {
|
if v(c, command) || c.Err != nil {
|
||||||
@@ -78,7 +111,7 @@ func checkCommand(c *Context, command *model.Command) bool {
|
|||||||
|
|
||||||
func logoutCommand(c *Context, command *model.Command) bool {
|
func logoutCommand(c *Context, command *model.Command) bool {
|
||||||
|
|
||||||
cmd := "/logout"
|
cmd := cmds["logoutCommand"]
|
||||||
|
|
||||||
if strings.Index(command.Command, cmd) == 0 {
|
if strings.Index(command.Command, cmd) == 0 {
|
||||||
command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Logout"})
|
command.AddSuggestion(&model.SuggestCommand{Suggestion: cmd, Description: "Logout"})
|
||||||
@@ -97,7 +130,7 @@ func logoutCommand(c *Context, command *model.Command) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func echoCommand(c *Context, command *model.Command) bool {
|
func echoCommand(c *Context, command *model.Command) bool {
|
||||||
cmd := "/echo"
|
cmd := cmds["echoCommand"]
|
||||||
maxThreads := 100
|
maxThreads := 100
|
||||||
|
|
||||||
if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
|
if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
|
||||||
@@ -162,7 +195,7 @@ func echoCommand(c *Context, command *model.Command) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func shrugCommand(c *Context, command *model.Command) bool {
|
func shrugCommand(c *Context, command *model.Command) bool {
|
||||||
cmd := "/shrug"
|
cmd := cmds["shrugCommand"]
|
||||||
|
|
||||||
if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
|
if !command.Suggest && strings.Index(command.Command, cmd) == 0 {
|
||||||
message := `¯\\\_(ツ)_/¯`
|
message := `¯\\\_(ツ)_/¯`
|
||||||
@@ -192,7 +225,7 @@ func shrugCommand(c *Context, command *model.Command) bool {
|
|||||||
func joinCommand(c *Context, command *model.Command) bool {
|
func joinCommand(c *Context, command *model.Command) bool {
|
||||||
|
|
||||||
// looks for "/join channel-name"
|
// looks for "/join channel-name"
|
||||||
cmd := "/join"
|
cmd := cmds["joinCommand"]
|
||||||
|
|
||||||
if strings.Index(command.Command, cmd) == 0 {
|
if strings.Index(command.Command, cmd) == 0 {
|
||||||
|
|
||||||
@@ -242,7 +275,7 @@ func joinCommand(c *Context, command *model.Command) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadTestCommand(c *Context, command *model.Command) bool {
|
func loadTestCommand(c *Context, command *model.Command) bool {
|
||||||
cmd := "/loadtest"
|
cmd := cmds["loadTestCommand"]
|
||||||
|
|
||||||
// This command is only available when EnableTesting is true
|
// This command is only available when EnableTesting is true
|
||||||
if !utils.Cfg.ServiceSettings.EnableTesting {
|
if !utils.Cfg.ServiceSettings.EnableTesting {
|
||||||
@@ -304,7 +337,7 @@ func contains(items []string, token string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadTestSetupCommand(c *Context, command *model.Command) bool {
|
func loadTestSetupCommand(c *Context, command *model.Command) bool {
|
||||||
cmd := "/loadtest setup"
|
cmd := cmds["loadTestCommand"] + " setup"
|
||||||
|
|
||||||
if strings.Index(command.Command, cmd) == 0 && !command.Suggest {
|
if strings.Index(command.Command, cmd) == 0 && !command.Suggest {
|
||||||
tokens := strings.Fields(strings.TrimPrefix(command.Command, cmd))
|
tokens := strings.Fields(strings.TrimPrefix(command.Command, cmd))
|
||||||
@@ -390,8 +423,8 @@ func loadTestSetupCommand(c *Context, command *model.Command) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadTestUsersCommand(c *Context, command *model.Command) bool {
|
func loadTestUsersCommand(c *Context, command *model.Command) bool {
|
||||||
cmd1 := "/loadtest users"
|
cmd1 := cmds["loadTestCommand"] + " users"
|
||||||
cmd2 := "/loadtest users fuzz"
|
cmd2 := cmds["loadTestCommand"] + " users fuzz"
|
||||||
|
|
||||||
if strings.Index(command.Command, cmd1) == 0 && !command.Suggest {
|
if strings.Index(command.Command, cmd1) == 0 && !command.Suggest {
|
||||||
cmd := cmd1
|
cmd := cmd1
|
||||||
@@ -420,8 +453,8 @@ func loadTestUsersCommand(c *Context, command *model.Command) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadTestChannelsCommand(c *Context, command *model.Command) bool {
|
func loadTestChannelsCommand(c *Context, command *model.Command) bool {
|
||||||
cmd1 := "/loadtest channels"
|
cmd1 := cmds["loadTestCommand"] + " channels"
|
||||||
cmd2 := "/loadtest channels fuzz"
|
cmd2 := cmds["loadTestCommand"] + " channels fuzz"
|
||||||
|
|
||||||
if strings.Index(command.Command, cmd1) == 0 && !command.Suggest {
|
if strings.Index(command.Command, cmd1) == 0 && !command.Suggest {
|
||||||
cmd := cmd1
|
cmd := cmd1
|
||||||
@@ -451,8 +484,8 @@ func loadTestChannelsCommand(c *Context, command *model.Command) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadTestPostsCommand(c *Context, command *model.Command) bool {
|
func loadTestPostsCommand(c *Context, command *model.Command) bool {
|
||||||
cmd1 := "/loadtest posts"
|
cmd1 := cmds["loadTestCommand"] + " posts"
|
||||||
cmd2 := "/loadtest posts fuzz"
|
cmd2 := cmds["loadTestCommand"] + " posts fuzz"
|
||||||
|
|
||||||
if strings.Index(command.Command, cmd1) == 0 && !command.Suggest {
|
if strings.Index(command.Command, cmd1) == 0 && !command.Suggest {
|
||||||
cmd := cmd1
|
cmd := cmd1
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RESP_EXECUTED = "executed"
|
RESP_EXECUTED = "executed"
|
||||||
|
RESP_NOT_IMPLEMENTED = "not implemented"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export default class CreatePost extends React.Component {
|
|||||||
this.getFileCount = this.getFileCount.bind(this);
|
this.getFileCount = this.getFileCount.bind(this);
|
||||||
this.handleArrowUp = this.handleArrowUp.bind(this);
|
this.handleArrowUp = this.handleArrowUp.bind(this);
|
||||||
this.handleResize = this.handleResize.bind(this);
|
this.handleResize = this.handleResize.bind(this);
|
||||||
|
this.sendMessage = this.sendMessage.bind(this);
|
||||||
|
|
||||||
PostStore.clearDraftUploads();
|
PostStore.clearDraftUploads();
|
||||||
|
|
||||||
@@ -122,6 +123,11 @@ export default class CreatePost extends React.Component {
|
|||||||
post.message,
|
post.message,
|
||||||
false,
|
false,
|
||||||
(data) => {
|
(data) => {
|
||||||
|
if (data.response === 'not implemented') {
|
||||||
|
this.sendMessage(post);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PostStore.storeDraft(data.channel_id, null);
|
PostStore.storeDraft(data.channel_id, null);
|
||||||
this.setState({messageText: '', submitting: false, postError: null, previews: [], serverError: null});
|
this.setState({messageText: '', submitting: false, postError: null, previews: [], serverError: null});
|
||||||
|
|
||||||
@@ -130,63 +136,70 @@ export default class CreatePost extends React.Component {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
const state = {};
|
if (err.sendMessage) {
|
||||||
state.serverError = err.message;
|
this.sendMessage(post);
|
||||||
state.submitting = false;
|
} else {
|
||||||
this.setState(state);
|
const state = {};
|
||||||
|
state.serverError = err.message;
|
||||||
|
state.submitting = false;
|
||||||
|
this.setState(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
post.channel_id = this.state.channelId;
|
this.sendMessage(post);
|
||||||
post.filenames = this.state.previews;
|
|
||||||
|
|
||||||
const time = Utils.getTimestamp();
|
|
||||||
const userId = UserStore.getCurrentId();
|
|
||||||
post.pending_post_id = `${userId}:${time}`;
|
|
||||||
post.user_id = userId;
|
|
||||||
post.create_at = time;
|
|
||||||
post.root_id = this.state.rootId;
|
|
||||||
post.parent_id = this.state.parentId;
|
|
||||||
|
|
||||||
const channel = ChannelStore.get(this.state.channelId);
|
|
||||||
|
|
||||||
PostStore.storePendingPost(post);
|
|
||||||
PostStore.storeDraft(channel.id, null);
|
|
||||||
this.setState({messageText: '', submitting: false, postError: null, previews: [], serverError: null});
|
|
||||||
|
|
||||||
Client.createPost(post, channel,
|
|
||||||
(data) => {
|
|
||||||
AsyncClient.getPosts();
|
|
||||||
|
|
||||||
const member = ChannelStore.getMember(channel.id);
|
|
||||||
member.msg_count = channel.total_msg_count;
|
|
||||||
member.last_viewed_at = Date.now();
|
|
||||||
ChannelStore.setChannelMember(member);
|
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
|
||||||
type: ActionTypes.RECIEVED_POST,
|
|
||||||
post: data
|
|
||||||
});
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
const state = {};
|
|
||||||
|
|
||||||
if (err.message === 'Invalid RootId parameter') {
|
|
||||||
if ($('#post_deleted').length > 0) {
|
|
||||||
$('#post_deleted').modal('show');
|
|
||||||
}
|
|
||||||
PostStore.removePendingPost(post.pending_post_id);
|
|
||||||
} else {
|
|
||||||
post.state = Constants.POST_FAILED;
|
|
||||||
PostStore.updatePendingPost(post);
|
|
||||||
}
|
|
||||||
|
|
||||||
state.submitting = false;
|
|
||||||
this.setState(state);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sendMessage(post) {
|
||||||
|
post.channel_id = this.state.channelId;
|
||||||
|
post.filenames = this.state.previews;
|
||||||
|
|
||||||
|
const time = Utils.getTimestamp();
|
||||||
|
const userId = UserStore.getCurrentId();
|
||||||
|
post.pending_post_id = `${userId}:${time}`;
|
||||||
|
post.user_id = userId;
|
||||||
|
post.create_at = time;
|
||||||
|
post.root_id = this.state.rootId;
|
||||||
|
post.parent_id = this.state.parentId;
|
||||||
|
|
||||||
|
const channel = ChannelStore.get(this.state.channelId);
|
||||||
|
|
||||||
|
PostStore.storePendingPost(post);
|
||||||
|
PostStore.storeDraft(channel.id, null);
|
||||||
|
this.setState({messageText: '', submitting: false, postError: null, previews: [], serverError: null});
|
||||||
|
|
||||||
|
Client.createPost(post, channel,
|
||||||
|
(data) => {
|
||||||
|
AsyncClient.getPosts();
|
||||||
|
|
||||||
|
const member = ChannelStore.getMember(channel.id);
|
||||||
|
member.msg_count = channel.total_msg_count;
|
||||||
|
member.last_viewed_at = Date.now();
|
||||||
|
ChannelStore.setChannelMember(member);
|
||||||
|
|
||||||
|
AppDispatcher.handleServerAction({
|
||||||
|
type: ActionTypes.RECIEVED_POST,
|
||||||
|
post: data
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
const state = {};
|
||||||
|
|
||||||
|
if (err.message === 'Invalid RootId parameter') {
|
||||||
|
if ($('#post_deleted').length > 0) {
|
||||||
|
$('#post_deleted').modal('show');
|
||||||
|
}
|
||||||
|
PostStore.removePendingPost(post.pending_post_id);
|
||||||
|
} else {
|
||||||
|
post.state = Constants.POST_FAILED;
|
||||||
|
PostStore.updatePendingPost(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.submitting = false;
|
||||||
|
this.setState(state);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
postMsgKeyPress(e) {
|
postMsgKeyPress(e) {
|
||||||
if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
|
if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user