diff --git a/README.md b/README.md index c8db5f98e..d40a5d1d8 100644 --- a/README.md +++ b/README.md @@ -30,39 +30,40 @@ Use this plugin to improve onboarding and HR processes. It adds a Welcome Bot th To configure the Welcome Bot, edit your `config.json` file with a message you want to send to a user in the following format: -``` - "Plugins": { - "com.mattermost.welcomebot": { - "WelcomeMessages": [ +```json +"Plugins": { + "com.mattermost.welcomebot": { + "WelcomeMessages": [ + { + "TeamName": "your-team-name", + "DelayInSeconds": 3, + "Message": [ + "Your welcome message here. Each list item specifies one line in the message text." + ], + "AttachmentMessage": [ + "Attachment message containing user actions" + ], + "Actions" : [ { - "TeamName": "your-team-name", - "DelayInSeconds": 3, - "IncludeGuests": false, - "Message": [ - "Your welcome message here. Each list item specifies one line in the message text." + "ActionType": "button", + "ActionDisplayName": "User Action", + "ActionName": "action-name", + "ActionDirectMessagePost": "Message send to new direct messages", + "ActionSuccessfulMessage": [ + "Message posted after the user takes this action and joins channels specified by 'ChannelsAddedTo'." ], - "AttachmentMessage": [ - "Attachment message containing user actions" - ], - "Actions" : [ - { - "ActionType": "button", - "ActionDisplayName": "User Action", - "ActionName": "action-name", - "ActionSuccessfulMessage": [ - "Message posted after the user takes this action and joins channels specified by 'ChannelsAddedTo'." - ], - "ChannelsAddedTo": ["channel-1", "channel-2"] - }, - { - "ActionType": "automatic", - "ChannelsAddedTo": ["channel-3", "channel-4"] - } - ] + "ChannelsAddedTo": ["channel-1", "channel-2", "@example-bot"] + }, + { + "ActionType": "automatic", + "ActionDirectMessagePost": "Message send to new direct messages", + "ChannelsAddedTo": ["channel-3", "channel-4", "@another-bot"] } ] } - }, + ] + } +}, ``` where @@ -78,6 +79,7 @@ where - **ActionName**: Sets the action name used by the plugin to identify which action is taken by a user. - **ActionSuccessfulMessage**: Message posted after the user takes this action and joins the specified channels. - **ChannelsAddedTo**: List of channel names the user is added to. Must be the channel handle used in the URL, in lowercase. For example, in the following URL the **channel name** value is `my-channel`: https://example.com/my-team/channels/my-channel + - **ActionDirectMessagePost**: The post to send users when creating the bot direct message channel The preview of the configured messages, as well as the creation of a channel welcome message, can be done via bot commands: * `/welcomebot help` - Displays usage information. diff --git a/server/action_context.go b/server/action_context.go index 14e2432ed..f36277687 100644 --- a/server/action_context.go +++ b/server/action_context.go @@ -2,9 +2,10 @@ package main // ActionContext passed from action buttons type ActionContext struct { - TeamID string `json:"team_id"` - UserID string `json:"user_id"` - Action string `json:"action"` + TeamID string `json:"team_id"` + UserID string `json:"user_id"` + Action string `json:"action"` + DirectMessagePost string `json:"direct_message_post"` } // Action type for decoding action buttons diff --git a/server/configuration.go b/server/configuration.go index 2b8123323..42e45b48e 100644 --- a/server/configuration.go +++ b/server/configuration.go @@ -19,6 +19,9 @@ type ConfigMessageAction struct { // The message that's display after this action was successful ActionSuccessfulMessage []string + // The message that is posted to direct message channels + ActionDirectMessagePost string + // The names of the channels that a users should be added to ChannelsAddedTo []string } diff --git a/server/welcomebot.go b/server/welcomebot.go index 7f65ad45f..3f319c99f 100644 --- a/server/welcomebot.go +++ b/server/welcomebot.go @@ -8,6 +8,7 @@ import ( "time" "github.com/mattermost/mattermost-server/v6/model" + "github.com/pkg/errors" ) func (p *Plugin) constructMessageTemplate(userID, teamID string) *MessageTemplate { @@ -109,6 +110,7 @@ func (p *Plugin) renderWelcomeMessage(messageTemplate MessageTemplate, configMes action.Context = &ActionContext{} action.Context.TeamID = messageTemplate.Team.Id action.Context.UserID = messageTemplate.User.Id + action.Context.DirectMessagePost = configAction.ActionDirectMessagePost action.Context.Action = "automatic" for _, channelName := range configAction.ChannelsAddedTo { @@ -121,9 +123,10 @@ func (p *Plugin) renderWelcomeMessage(messageTemplate MessageTemplate, configMes Name: configAction.ActionDisplayName, Integration: &model.PostActionIntegration{ Context: map[string]interface{}{ - "action": configAction.ActionName, - "team_id": messageTemplate.Team.Id, - "user_id": messageTemplate.User.Id, + "action": configAction.ActionName, + "team_id": messageTemplate.Team.Id, + "user_id": messageTemplate.User.Id, + "direct_message_post": configAction.ActionDirectMessagePost, }, URL: fmt.Sprintf("%v/plugins/%v/addchannels", p.getSiteURL(), manifest.ID), }, @@ -228,12 +231,54 @@ func (p *Plugin) processActionMessage(messageTemplate MessageTemplate, action *A } func (p *Plugin) joinChannel(action *Action, channelName string) { - if channel, err := p.API.GetChannelByName(action.Context.TeamID, channelName, false); err == nil { - if _, err := p.API.AddChannelMember(channel.Id, action.Context.UserID); err != nil { - p.API.LogError("Couldn't add user to the channel, continuing to next channel", "user_id", action.Context.UserID, "channel_id", channel.Id) + // If it begins with @ create a DM channel + if strings.HasPrefix(channelName, "@") { + if err := p.handleDMs(action, channelName); err != nil { + p.API.LogError("failed to handle DM channel, continuing to next channel. " + err.Error()) + } + } else { // Otherwise treat it like a normal channel + if channel, err := p.API.GetChannelByName(action.Context.TeamID, channelName, false); err == nil { + if _, err := p.API.AddChannelMember(channel.Id, action.Context.UserID); err != nil { + p.API.LogError("Couldn't add user to the channel, continuing to next channel", "channel_name", channelName, "user_id", action.Context.UserID, channel.Id) + return + } + } else { + p.API.LogError("failed to get channel, continuing to the next channel", "channel_name", channelName, "user_id", action.Context.UserID) return } - } else { - p.API.LogError("failed to get channel, continuing to the next channel", "channel_name", channelName, "user_id", action.Context.UserID) } } + +func (p *Plugin) handleDMs(action *Action, channelName string) error { + username := channelName[1:] + dmUser, userErr := p.API.GetUserByUsername(username) + if userErr != nil { + return errors.Wrapf(userErr, "couldn't find DM channel for username %s", username) + } + + if !dmUser.IsBot { + return errors.Wrapf(userErr, "Specified DM user is not a bot for username %s", username) + } + + dmChannel, err := p.API.GetDirectChannel(dmUser.Id, action.Context.UserID) + if err != nil { + return errors.Wrapf(err, "Couldn't create or get DM channel for user_id %s and channel_id %s", action.Context.UserID, dmChannel.Id) + } + + dmMessage := "Welcome to the team!" + if len(action.Context.DirectMessagePost) != 0 { + dmMessage = action.Context.DirectMessagePost + } + + post := &model.Post{ + Message: dmMessage, + ChannelId: dmChannel.Id, + UserId: dmUser.Id, + } + + if _, err := p.API.CreatePost(post); err != nil { + return errors.Wrapf(err, "Could not create direct message for user_id %s", post.UserId) + } + + return nil +}