func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model.AppError) { if len(otherUserId) != 26 { return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId) } uc := Srv.Store.User().Get(otherUserId) channel := new(model.Channel) channel.DisplayName = "" channel.Name = model.GetDMNameFromIds(otherUserId, c.Session.UserId) channel.TeamId = c.Session.TeamId channel.Description = "" channel.Type = model.CHANNEL_DIRECT if uresult := <-uc; uresult.Err != nil { return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId) } if sc, err := CreateChannel(c, channel, true); err != nil { return nil, err } else { cm := &model.ChannelMember{ChannelId: sc.Id, UserId: otherUserId, Roles: "", NotifyLevel: model.CHANNEL_NOTIFY_ALL} if cmresult := <-Srv.Store.Channel().SaveMember(cm); cmresult.Err != nil { return nil, cmresult.Err } return sc, nil } }
func (me *msgProvider) DoCommand(c *Context, channelId string, message string) *model.CommandResponse { splitMessage := strings.SplitN(message, " ", 2) parsedMessage := "" targetUser := "" if len(splitMessage) > 1 { parsedMessage = strings.SplitN(message, " ", 2)[1] } targetUser = strings.SplitN(message, " ", 2)[0] targetUser = strings.TrimPrefix(targetUser, "@") if profileList := <-Srv.Store.User().GetProfiles(c.Session.TeamId); profileList.Err != nil { c.Err = profileList.Err return &model.CommandResponse{Text: c.T("api.command_msg.list.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } else { profileUsers := profileList.Data.(map[string]*model.User) for _, userProfile := range profileUsers { //Don't let users open DMs with themselves. It probably won't work out well. if userProfile.Id == c.Session.UserId { continue } if userProfile.Username == targetUser { targetChannelId := "" //Find the channel based on this user channelName := model.GetDMNameFromIds(c.Session.UserId, userProfile.Id) if channel := <-Srv.Store.Channel().GetByName(c.Session.TeamId, channelName); channel.Err != nil { if channel.Err.Id == "store.sql_channel.get_by_name.missing.app_error" { if directChannel, err := CreateDirectChannel(c, userProfile.Id); err != nil { c.Err = err return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } else { targetChannelId = directChannel.Id } } else { c.Err = channel.Err return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } } else { targetChannelId = channel.Data.(*model.Channel).Id } makeDirectChannelVisible(c.Session.TeamId, targetChannelId) if len(parsedMessage) > 0 { post := &model.Post{} post.Message = parsedMessage post.ChannelId = targetChannelId if _, err := CreatePost(c, post, true); err != nil { return &model.CommandResponse{Text: c.T("api.command_msg.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } } return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + channelName, Text: c.T("api.command_msg.success"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } } } return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} }
func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { uc := Srv.Store.User().Get(otherUserId) channel := new(model.Channel) channel.DisplayName = "" channel.Name = model.GetDMNameFromIds(otherUserId, userId) channel.Header = "" channel.Type = model.CHANNEL_DIRECT if uresult := <-uc; uresult.Err != nil { return nil, model.NewLocAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId) } cm1 := &model.ChannelMember{ UserId: userId, NotifyProps: model.GetDefaultChannelNotifyProps(), } cm2 := &model.ChannelMember{ UserId: otherUserId, NotifyProps: model.GetDefaultChannelNotifyProps(), } if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil { if result.Err.Id == store.CHANNEL_EXISTS_ERROR { return result.Data.(*model.Channel), nil } else { return nil, result.Err } } else { return result.Data.(*model.Channel), nil } }
func (me *msgProvider) DoCommand(c *Context, args *model.CommandArgs, message string) *model.CommandResponse { splitMessage := strings.SplitN(message, " ", 2) parsedMessage := "" targetUsername := "" if len(splitMessage) > 1 { parsedMessage = strings.SplitN(message, " ", 2)[1] } targetUsername = strings.SplitN(message, " ", 2)[0] targetUsername = strings.TrimPrefix(targetUsername, "@") var userProfile *model.User if result := <-app.Srv.Store.User().GetByUsername(targetUsername); result.Err != nil { c.Err = result.Err return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } else { userProfile = result.Data.(*model.User) } if userProfile.Id == c.Session.UserId { return &model.CommandResponse{Text: c.T("api.command_msg.missing.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } // Find the channel based on this user channelName := model.GetDMNameFromIds(c.Session.UserId, userProfile.Id) targetChannelId := "" if channel := <-app.Srv.Store.Channel().GetByName(c.TeamId, channelName); channel.Err != nil { if channel.Err.Id == "store.sql_channel.get_by_name.missing.app_error" { if directChannel, err := app.CreateDirectChannel(c.Session.UserId, userProfile.Id); err != nil { c.Err = err return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } else { targetChannelId = directChannel.Id } } else { c.Err = channel.Err return &model.CommandResponse{Text: c.T("api.command_msg.dm_fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } } else { targetChannelId = channel.Data.(*model.Channel).Id } app.MakeDirectChannelVisible(targetChannelId) if len(parsedMessage) > 0 { post := &model.Post{} post.Message = parsedMessage post.ChannelId = targetChannelId post.UserId = c.Session.UserId if _, err := app.CreatePost(post, c.TeamId, true); err != nil { return &model.CommandResponse{Text: c.T("api.command_msg.fail.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} } } return &model.CommandResponse{GotoLocation: c.GetTeamURL() + "/channels/" + channelName, Text: "", ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL} }
func (m *MatterMail) getDirectChannelIDByName(client *model.Client, channelList *model.ChannelList, userName string) string { if m.user.Username == userName { m.eror.Printf("Impossible create a Direct channel, Mattermail user (%v) equals destination user (%v)\n", m.user.Username, userName) return "" } //result, err := client.GetProfilesForDirectMessageList(client.GetTeamId()) result, err := client.SearchUsers(model.UserSearch{ AllowInactive: false, TeamId: client.GetTeamId(), Term: userName, }) if err != nil { m.eror.Println("Error on SearchUsers: ", err.Error()) return "" } profiles := result.Data.([]*model.User) var userID string for _, p := range profiles { if p.Username == userName { userID = p.Id break } } if userID == "" { m.debg.Println("Did not find the username:"******"" } dmName := model.GetDMNameFromIds(m.user.Id, userID) dmID := getChannelIDByName(channelList, dmName) if dmID != "" { return dmID } m.debg.Println("Create direct channel to user:"******"Error on CreateDirectChannel: ", err.Error()) return "" } directChannel := result.Data.(*model.Channel) return directChannel.Id }
// SendDirectMessage sends a direct message to specified user func (m *MMClient) SendDirectMessage(toUserId string, msg string) { m.log.Debugf("SendDirectMessage to %s, msg %s", toUserId, msg) // create DM channel (only happens on first message) _, err := m.Client.CreateDirectChannel(toUserId) if err != nil { m.log.Debugf("SendDirectMessage to %#v failed: %s", toUserId, err) } channelName := model.GetDMNameFromIds(toUserId, m.User.Id) // update our channels mmchannels, _ := m.Client.GetChannels("") m.Lock() m.Team.Channels = mmchannels.Data.(*model.ChannelList) m.Unlock() // build & send the message msg = strings.Replace(msg, "\r", "", -1) post := &model.Post{ChannelId: m.GetChannelId(channelName, ""), Message: msg} m.Client.CreatePost(post) }
func CreateDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { uc := Srv.Store.User().Get(otherUserId) channel := new(model.Channel) channel.DisplayName = "" channel.Name = model.GetDMNameFromIds(otherUserId, userId) channel.Header = "" channel.Type = model.CHANNEL_DIRECT if uresult := <-uc; uresult.Err != nil { return nil, model.NewLocAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId) } cm1 := &model.ChannelMember{ UserId: userId, NotifyProps: model.GetDefaultChannelNotifyProps(), Roles: model.ROLE_CHANNEL_USER.Id, } cm2 := &model.ChannelMember{ UserId: otherUserId, NotifyProps: model.GetDefaultChannelNotifyProps(), Roles: model.ROLE_CHANNEL_USER.Id, } if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil { if result.Err.Id == store.CHANNEL_EXISTS_ERROR { return result.Data.(*model.Channel), nil } else { return nil, result.Err } } else { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil) message.Add("teammate_id", otherUserId) go Publish(message) return result.Data.(*model.Channel), nil } }
func (s SqlChannelStore) CreateDirectChannel(userId string, otherUserId string) StoreChannel { channel := new(model.Channel) channel.DisplayName = "" channel.Name = model.GetDMNameFromIds(otherUserId, userId) channel.Header = "" channel.Type = model.CHANNEL_DIRECT cm1 := &model.ChannelMember{ UserId: userId, NotifyProps: model.GetDefaultChannelNotifyProps(), Roles: model.ROLE_CHANNEL_USER.Id, } cm2 := &model.ChannelMember{ UserId: otherUserId, NotifyProps: model.GetDefaultChannelNotifyProps(), Roles: model.ROLE_CHANNEL_USER.Id, } return s.SaveDirectChannel(channel, cm1, cm2) }
func CreateDirectChannel(c *Context, otherUserId string) (*model.Channel, *model.AppError) { if len(otherUserId) != 26 { return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId) } uc := Srv.Store.User().Get(otherUserId) channel := new(model.Channel) channel.DisplayName = "" channel.Name = model.GetDMNameFromIds(otherUserId, c.Session.UserId) channel.TeamId = c.Session.TeamId channel.Header = "" channel.Type = model.CHANNEL_DIRECT if uresult := <-uc; uresult.Err != nil { return nil, model.NewAppError("CreateDirectChannel", "Invalid other user id ", otherUserId) } cm1 := &model.ChannelMember{ UserId: c.Session.UserId, Roles: model.CHANNEL_ROLE_ADMIN, NotifyProps: model.GetDefaultChannelNotifyProps(), } cm2 := &model.ChannelMember{ UserId: otherUserId, Roles: "", NotifyProps: model.GetDefaultChannelNotifyProps(), } if result := <-Srv.Store.Channel().SaveDirectChannel(channel, cm1, cm2); result.Err != nil { return nil, result.Err } else { return result.Data.(*model.Channel), nil } }
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks { c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) id := params["id"] hchan := api.Srv.Store.Webhook().GetIncoming(id) r.ParseForm() var props map[string]string if r.Header.Get("Content-Type") == "application/json" { props = model.MapFromJson(r.Body) } else { props = model.MapFromJson(strings.NewReader(r.FormValue("payload"))) } text := props["text"] if len(text) == 0 { c.Err = model.NewAppError("incomingWebhook", "No text specified", "") return } channelName := props["channel"] var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message) return } else { hook = result.Data.(*model.IncomingWebhook) } var channel *model.Channel var cchan store.StoreChannel if len(channelName) != 0 { if channelName[0] == '@' { if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message) return } else { channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] } cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName) } else { cchan = api.Srv.Store.Channel().Get(hook.ChannelId) } overrideUsername := props["username"] overrideIconUrl := props["icon_url"] if result := <-cchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message) return } else { channel = result.Data.(*model.Channel) } pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId) // create a mock session c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false} if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN { c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "") return } if _, err := api.CreateWebhookPost(c, channel.Id, text, overrideUsername, overrideIconUrl); err != nil { c.Err = err return } w.Header().Set("Content-Type", "text/plain") w.Write([]byte("ok")) }
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks { c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) id := params["id"] hchan := api.Srv.Store.Webhook().GetIncoming(id) r.ParseForm() var parsedRequest *model.IncomingWebhookRequest if r.Header.Get("Content-Type") == "application/json" { parsedRequest = model.IncomingWebhookRequestFromJson(r.Body) } else { parsedRequest = model.IncomingWebhookRequestFromJson(strings.NewReader(r.FormValue("payload"))) } if parsedRequest == nil { c.Err = model.NewAppError("incomingWebhook", "Unable to parse incoming data", "") return } text := parsedRequest.Text if len(text) == 0 && parsedRequest.Attachments == nil { c.Err = model.NewAppError("incomingWebhook", "No text specified", "") return } channelName := parsedRequest.ChannelName webhookType := parsedRequest.Type //attachments is in here for slack compatibility if parsedRequest.Attachments != nil { if len(parsedRequest.Props) == 0 { parsedRequest.Props = make(model.StringInterface) } parsedRequest.Props["attachments"] = parsedRequest.Attachments webhookType = model.POST_SLACK_ATTACHMENT } var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message) return } else { hook = result.Data.(*model.IncomingWebhook) } var channel *model.Channel var cchan store.StoreChannel if len(channelName) != 0 { if channelName[0] == '@' { if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message) return } else { channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] } cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName) } else { cchan = api.Srv.Store.Channel().Get(hook.ChannelId) } overrideUsername := parsedRequest.Username overrideIconUrl := parsedRequest.IconURL if result := <-cchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message) return } else { channel = result.Data.(*model.Channel) } pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId) // create a mock session c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false} if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN { c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "") return } if _, err := api.CreateWebhookPost(c, channel.Id, text, overrideUsername, overrideIconUrl, parsedRequest.Props, webhookType); err != nil { c.Err = err return } w.Header().Set("Content-Type", "text/plain") w.Write([]byte("ok")) }
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) id := params["id"] hchan := api.Srv.Store.Webhook().GetIncoming(id) r.ParseForm() props := model.MapFromJson(strings.NewReader(r.FormValue("payload"))) text := props["text"] if len(text) == 0 { c.Err = model.NewAppError("incomingWebhook", "No text specified", "") return } channelName := props["channel"] var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message) return } else { hook = result.Data.(*model.IncomingWebhook) } var channel *model.Channel var cchan store.StoreChannel if len(channelName) != 0 { if channelName[0] == '@' { if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message) return } else { channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] } cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName) } else { cchan = api.Srv.Store.Channel().Get(hook.ChannelId) } // parse links into Markdown format linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`) text = linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})") linkRegex := regexp.MustCompile(`<\s*(\S*)\s*>`) text = linkRegex.ReplaceAllString(text, "${1}") if result := <-cchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message) return } else { channel = result.Data.(*model.Channel) } pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId) post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text} if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN { c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "") return } // create a mock session c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false} if _, err := api.CreatePost(c, post, false); err != nil { c.Err = model.NewAppError("incomingWebhook", "Error creating post", "err="+err.Message) return } w.Header().Set("Content-Type", "text/plain") w.Write([]byte("ok")) }
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks { c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) id := params["id"] hchan := api.Srv.Store.Webhook().GetIncoming(id) r.ParseForm() var props map[string]string if r.Header.Get("Content-Type") == "application/json" { props = model.MapFromJson(r.Body) } else { props = model.MapFromJson(strings.NewReader(r.FormValue("payload"))) } text := props["text"] if len(text) == 0 { c.Err = model.NewAppError("incomingWebhook", "No text specified", "") return } channelName := props["channel"] overrideUsername := props["username"] overrideIconUrl := props["icon_url"] var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message) return } else { hook = result.Data.(*model.IncomingWebhook) } var channel *model.Channel var cchan store.StoreChannel if len(channelName) != 0 { if channelName[0] == '@' { if result := <-api.Srv.Store.User().GetByUsername(hook.TeamId, channelName[1:]); result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the user", "err="+result.Err.Message) return } else { channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] } cchan = api.Srv.Store.Channel().GetByName(hook.TeamId, channelName) } else { cchan = api.Srv.Store.Channel().Get(hook.ChannelId) } // parse links into Markdown format linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`) text = linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})") linkRegex := regexp.MustCompile(`<\s*(\S*)\s*>`) text = linkRegex.ReplaceAllString(text, "${1}") if result := <-cchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message) return } else { channel = result.Data.(*model.Channel) } pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId) post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text} post.AddProp("from_webhook", "true") if utils.Cfg.ServiceSettings.EnablePostUsernameOverride { if len(overrideUsername) != 0 { post.AddProp("override_username", overrideUsername) } else { post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME) } } if utils.Cfg.ServiceSettings.EnablePostIconOverride { if len(overrideIconUrl) != 0 { post.AddProp("override_icon_url", overrideIconUrl) } else { post.AddProp("override_icon_url", model.DEFAULT_WEBHOOK_ICON) } } if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN { c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "") return } // create a mock session c.Session = model.Session{UserId: hook.UserId, TeamId: hook.TeamId, IsOAuth: false} if _, err := api.CreatePost(c, post, false); err != nil { c.Err = model.NewAppError("incomingWebhook", "Error creating post", "err="+err.Message) return } w.Header().Set("Content-Type", "text/plain") w.Write([]byte("ok")) }
func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) id := params["id"] hchan := app.Srv.Store.Webhook().GetIncoming(id) r.ParseForm() var payload io.Reader contentType := r.Header.Get("Content-Type") if strings.Split(contentType, "; ")[0] == "application/x-www-form-urlencoded" { payload = strings.NewReader(r.FormValue("payload")) } else { payload = r.Body } if utils.Cfg.LogSettings.EnableWebhookDebugging { var err error payload, err = utils.DebugReader( payload, utils.T("api.webhook.incoming.debug"), ) if err != nil { c.Err = model.NewLocAppError( "incomingWebhook", "api.webhook.incoming.debug.error", nil, err.Error(), ) return } } parsedRequest := model.IncomingWebhookRequestFromJson(payload) if parsedRequest == nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.parse.app_error", nil, "") return } text := parsedRequest.Text if len(text) == 0 && parsedRequest.Attachments == nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.text.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } textSize := utf8.RuneCountInString(text) if textSize > model.POST_MESSAGE_MAX_RUNES { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.text.length.app_error", map[string]interface{}{"Max": model.POST_MESSAGE_MAX_RUNES, "Actual": textSize}, "") c.Err.StatusCode = http.StatusBadRequest return } channelName := parsedRequest.ChannelName webhookType := parsedRequest.Type // attachments is in here for slack compatibility if parsedRequest.Attachments != nil { if len(parsedRequest.Props) == 0 { parsedRequest.Props = make(model.StringInterface) } parsedRequest.Props["attachments"] = parsedRequest.Attachments attachmentSize := utf8.RuneCountInString(model.StringInterfaceToJson(parsedRequest.Props)) // Minus 100 to leave room for setting post type in the Props if attachmentSize > model.POST_PROPS_MAX_RUNES-100 { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.attachment.app_error", map[string]interface{}{"Max": model.POST_PROPS_MAX_RUNES - 100, "Actual": attachmentSize}, "") c.Err.StatusCode = http.StatusBadRequest return } webhookType = model.POST_SLACK_ATTACHMENT } var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.invalid.app_error", nil, "err="+result.Err.Message) return } else { hook = result.Data.(*model.IncomingWebhook) } var channel *model.Channel var cchan store.StoreChannel var directUserId string if len(channelName) != 0 { if channelName[0] == '@' { if result := <-app.Srv.Store.User().GetByUsername(channelName[1:]); result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message) return } else { directUserId = result.Data.(*model.User).Id channelName = model.GetDMNameFromIds(directUserId, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] } cchan = app.Srv.Store.Channel().GetByName(hook.TeamId, channelName) } else { cchan = app.Srv.Store.Channel().Get(hook.ChannelId, true) } overrideUsername := parsedRequest.Username overrideIconUrl := parsedRequest.IconURL result := <-cchan if result.Err != nil && result.Err.Id == store.MISSING_CHANNEL_ERROR && directUserId != "" { newChanResult := <-app.Srv.Store.Channel().CreateDirectChannel(directUserId, hook.UserId) if newChanResult.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+newChanResult.Err.Message) return } else { channel = newChanResult.Data.(*model.Channel) app.InvalidateCacheForUser(directUserId) app.InvalidateCacheForUser(hook.UserId) } } else if result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message) return } else { channel = result.Data.(*model.Channel) } // create a mock session c.Session = model.Session{ UserId: hook.UserId, TeamMembers: []*model.TeamMember{{ TeamId: hook.TeamId, UserId: hook.UserId, Roles: model.ROLE_CHANNEL_USER.Id, }}, IsOAuth: false, } c.TeamId = hook.TeamId if channel.Type != model.CHANNEL_OPEN && !HasPermissionToChannelContext(c, channel.Id, model.PERMISSION_READ_CHANNEL) { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "") return } c.Err = nil if _, err := app.CreateWebhookPost(hook.UserId, hook.TeamId, channel.Id, text, overrideUsername, overrideIconUrl, parsedRequest.Props, webhookType); err != nil { c.Err = err return } w.Header().Set("Content-Type", "text/plain") w.Write([]byte("ok")) }
func incomingWebhook(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) id := params["id"] hchan := Srv.Store.Webhook().GetIncoming(id) r.ParseForm() var parsedRequest *model.IncomingWebhookRequest contentType := r.Header.Get("Content-Type") if strings.Split(contentType, "; ")[0] == "application/x-www-form-urlencoded" { parsedRequest = model.IncomingWebhookRequestFromJson(strings.NewReader(r.FormValue("payload"))) } else { parsedRequest = model.IncomingWebhookRequestFromJson(r.Body) } if parsedRequest == nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.parse.app_error", nil, "") return } text := parsedRequest.Text if len(text) == 0 && parsedRequest.Attachments == nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.text.app_error", nil, "") return } channelName := parsedRequest.ChannelName webhookType := parsedRequest.Type //attachments is in here for slack compatibility if parsedRequest.Attachments != nil { if len(parsedRequest.Props) == 0 { parsedRequest.Props = make(model.StringInterface) } parsedRequest.Props["attachments"] = parsedRequest.Attachments webhookType = model.POST_SLACK_ATTACHMENT } var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.invalid.app_error", nil, "err="+result.Err.Message) return } else { hook = result.Data.(*model.IncomingWebhook) } var channel *model.Channel var cchan store.StoreChannel if len(channelName) != 0 { if channelName[0] == '@' { if result := <-Srv.Store.User().GetByUsername(channelName[1:]); result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.user.app_error", nil, "err="+result.Err.Message) return } else { channelName = model.GetDMNameFromIds(result.Data.(*model.User).Id, hook.UserId) } } else if channelName[0] == '#' { channelName = channelName[1:] } cchan = Srv.Store.Channel().GetByName(hook.TeamId, channelName) } else { cchan = Srv.Store.Channel().Get(hook.ChannelId) } overrideUsername := parsedRequest.Username overrideIconUrl := parsedRequest.IconURL if result := <-cchan; result.Err != nil { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message) return } else { channel = result.Data.(*model.Channel) } pchan := Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId) // create a mock session c.Session = model.Session{ UserId: hook.UserId, TeamMembers: []*model.TeamMember{{TeamId: hook.TeamId, UserId: hook.UserId}}, IsOAuth: false, } if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN { c.Err = model.NewLocAppError("incomingWebhook", "web.incoming_webhook.permissions.app_error", nil, "") return } if _, err := CreateWebhookPost(c, channel.Id, text, overrideUsername, overrideIconUrl, parsedRequest.Props, webhookType); err != nil { c.Err = err return } w.Header().Set("Content-Type", "text/plain") w.Write([]byte("ok")) }