diff --git a/app/bot.go b/app/bot.go index 7225c9b7c7..5db560598d 100644 --- a/app/bot.go +++ b/app/bot.go @@ -62,7 +62,11 @@ func (a *App) CreateBot(bot *model.Bot) (*model.Bot, *model.AppError) { } else if ownerUser != nil { // Send a message to the bot's creator to inform them that the bot needs to be added // to a team and channel after it's created - channel, err := a.GetOrCreateDirectChannel(savedBot.UserId, bot.OwnerId) + botOwner, err := a.GetUser(bot.OwnerId) + if err != nil { + return nil, err + } + channel, err := a.getOrCreateDirectChannelWithUser(user, botOwner) if err != nil { return nil, err } diff --git a/app/bot_test.go b/app/bot_test.go index 3b413e0428..a089fac876 100644 --- a/app/bot_test.go +++ b/app/bot_test.go @@ -76,8 +76,11 @@ func TestCreateBot(t *testing.T) { assert.Equal(t, "a bot", bot.Description) assert.Equal(t, th.BasicUser.Id, bot.OwnerId) + user, err := th.App.GetUser(bot.UserId) + require.Nil(t, err) + // Check that a post was created to add bot to team and channels - channel, err := th.App.GetOrCreateDirectChannel(bot.UserId, th.BasicUser.Id) + channel, err := th.App.getOrCreateDirectChannelWithUser(user, th.BasicUser) require.Nil(t, err) posts, err := th.App.GetPosts(channel.Id, 0, 1) require.Nil(t, err) diff --git a/app/channel.go b/app/channel.go index 0d39c7cfd0..344083dff5 100644 --- a/app/channel.go +++ b/app/channel.go @@ -339,7 +339,34 @@ func (a *App) GetOrCreateDirectChannel(userID, otherUserID string) (*model.Chann } a.WaitForChannelMembership(channel.Id, userID) + a.handleCreationEvent(userID, otherUserID, channel) + return channel, nil +} +func (a *App) getOrCreateDirectChannelWithUser(user, otherUser *model.User) (*model.Channel, *model.AppError) { + channel, nErr := a.getDirectChannel(user.Id, otherUser.Id) + if nErr != nil { + return nil, nErr + } + + if channel != nil { + return channel, nil + } + + channel, err := a.createDirectChannelWithUser(user, otherUser) + if err != nil { + if err.Id == store.ChannelExistsError { + return channel, nil + } + return nil, err + } + + a.WaitForChannelMembership(channel.Id, user.Id) + a.handleCreationEvent(user.Id, otherUser.Id, channel) + return channel, nil +} + +func (a *App) handleCreationEvent(userID, otherUserID string, channel *model.Channel) { a.InvalidateCacheForUser(userID) a.InvalidateCacheForUser(otherUserID) @@ -356,11 +383,9 @@ func (a *App) GetOrCreateDirectChannel(userID, otherUserID string) (*model.Chann message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil) message.Add("teammate_id", otherUserID) a.Publish(message) - - return channel, nil } -func (a *App) createDirectChannel(userID string, otherUserID string) (*model.Channel, *model.AppError) { +func (a *App) createDirectChannel(userID, otherUserID string) (*model.Channel, *model.AppError) { users, err := a.Srv().Store.User().GetMany([]string{userID, otherUserID}) if err != nil { return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, err.Error(), http.StatusBadRequest) @@ -390,7 +415,10 @@ func (a *App) createDirectChannel(userID string, otherUserID string) (*model.Cha user = users[1] otherUser = users[0] } + return a.createDirectChannelWithUser(user, otherUser) +} +func (a *App) createDirectChannelWithUser(user, otherUser *model.User) (*model.Channel, *model.AppError) { channel, nErr := a.Srv().Store.Channel().CreateDirectChannel(user, otherUser) if nErr != nil { var invErr *store.ErrInvalidInput @@ -401,34 +429,34 @@ func (a *App) createDirectChannel(userID string, otherUserID string) (*model.Cha case errors.As(nErr, &invErr): switch { case invErr.Entity == "Channel" && invErr.Field == "DeleteAt": - return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) + return nil, model.NewAppError("createDirectChannelWithUser", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) case invErr.Entity == "Channel" && invErr.Field == "Type": - return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest) + return nil, model.NewAppError("createDirectChannelWithUser", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest) case invErr.Entity == "Channel" && invErr.Field == "Id": return nil, model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.existing.app_error", nil, "id="+invErr.Value.(string), http.StatusBadRequest) } case errors.As(nErr, &cErr): switch cErr.Resource { case "Channel": - return channel, model.NewAppError("CreateChannel", store.ChannelExistsError, nil, cErr.Error(), http.StatusBadRequest) + return channel, model.NewAppError("createDirectChannelWithUser", store.ChannelExistsError, nil, cErr.Error(), http.StatusBadRequest) case "ChannelMembers": - return nil, model.NewAppError("CreateChannel", "app.channel.save_member.exists.app_error", nil, cErr.Error(), http.StatusBadRequest) + return nil, model.NewAppError("createDirectChannelWithUser", "app.channel.save_member.exists.app_error", nil, cErr.Error(), http.StatusBadRequest) } case errors.As(nErr, <Err): - return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest) + return nil, model.NewAppError("createDirectChannelWithUser", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest) case errors.As(nErr, &appErr): // in case we haven't converted to plain error. return nil, appErr default: // last fallback in case it doesn't map to an existing app error. - return nil, model.NewAppError("CreateDirectChannel", "app.channel.create_direct_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError) + return nil, model.NewAppError("createDirectChannelWithUser", "app.channel.create_direct_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError) } } - if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(userID, channel.Id, model.GetMillis()); err != nil { - return nil, model.NewAppError("CreateDirectChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) + if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); err != nil { + return nil, model.NewAppError("createDirectChannelWithUser", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) } - if userID != otherUserID { - if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(otherUserID, channel.Id, model.GetMillis()); err != nil { - return nil, model.NewAppError("CreateDirectChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) + if user.Id != otherUser.Id { + if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(otherUser.Id, channel.Id, model.GetMillis()); err != nil { + return nil, model.NewAppError("createDirectChannelWithUser", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) } }