Added ephemeral messages sent when a user mentions someone not in the channel
Этот коммит содержится в:
47
api/post.go
47
api/post.go
@@ -15,6 +15,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -249,7 +250,7 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendNotificationsAndForget(c, post, team, channel)
|
sendNotificationsAndForget(c, post, team, channel)
|
||||||
go checkForOutOfChannelMentions(post, channel)
|
go checkForOutOfChannelMentions(c, post, channel)
|
||||||
|
|
||||||
var user *model.User
|
var user *model.User
|
||||||
if result := <-uchan; result.Err != nil {
|
if result := <-uchan; result.Err != nil {
|
||||||
@@ -729,18 +730,52 @@ func updateMentionCountAndForget(channelId, userId string) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkForOutOfChannelMentions(post *model.Post, channel *model.Channel) {
|
func checkForOutOfChannelMentions(c *Context, post *model.Post, channel *model.Channel) {
|
||||||
// don't check for out of channel mentions in direct channels
|
// don't check for out of channel mentions in direct channels
|
||||||
if channel.Type == model.CHANNEL_DIRECT {
|
if channel.Type == model.CHANNEL_DIRECT {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mentioned := getOutOfChannelMentions(post, channel.TeamId)
|
mentioned := getOutOfChannelMentions(post, channel.TeamId)
|
||||||
|
if len(mentioned) == 0 {
|
||||||
// TODO come up with a way to alert the client of these
|
return
|
||||||
for _, user := range mentioned {
|
|
||||||
l4g.Debug("%v was mentioned and wasn't in the channel", user.Username)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usernames := make([]string, len(mentioned))
|
||||||
|
for i, user := range mentioned {
|
||||||
|
usernames[i] = user.Username
|
||||||
|
}
|
||||||
|
sort.Strings(usernames)
|
||||||
|
|
||||||
|
var messageText string
|
||||||
|
if len(usernames) == 1 {
|
||||||
|
messageText = c.T("api.post.check_for_out_of_channel_mentions.message.one", map[string]interface{}{
|
||||||
|
"Username": usernames[0],
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
messageText = c.T("api.post.check_for_out_of_channel_mentions.message.multiple", map[string]interface{}{
|
||||||
|
"Usernames": strings.Join(usernames[:len(usernames)-1], ", "),
|
||||||
|
"LastUsername": usernames[len(usernames)-1],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an ephemeral post that will be sent only to the sender of this original post and not stored in the DB
|
||||||
|
warningPost := model.Post{
|
||||||
|
Id: model.NewId(),
|
||||||
|
ChannelId: post.ChannelId,
|
||||||
|
Message: messageText,
|
||||||
|
Type: model.POST_OUT_OF_CHANNEL_MENTION,
|
||||||
|
CreateAt: post.CreateAt + 1,
|
||||||
|
Ephemeral: true,
|
||||||
|
Props: model.StringInterface{},
|
||||||
|
Filenames: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
message := model.NewMessage(c.Session.TeamId, channel.Id, post.UserId, model.ACTION_EPHEMERAL_MESSAGE)
|
||||||
|
message.Add("post", warningPost.ToJson())
|
||||||
|
message.Add("channel_type", channel.Type)
|
||||||
|
|
||||||
|
PublishAndForget(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a list of users that were mentioned in a given post that aren't in the channel that the post was made in
|
// Gets a list of users that were mentioned in a given post that aren't in the channel that the post was made in
|
||||||
|
|||||||
@@ -101,6 +101,9 @@ func ShouldSendEvent(webCon *WebConn, msg *model.Message) bool {
|
|||||||
return false
|
return false
|
||||||
} else if msg.Action == model.ACTION_PREFERENCE_CHANGED {
|
} else if msg.Action == model.ACTION_PREFERENCE_CHANGED {
|
||||||
return false
|
return false
|
||||||
|
} else if msg.Action == model.ACTION_EPHEMERAL_MESSAGE {
|
||||||
|
// For now, ephemeral messages are sent directly to individual users
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only report events to a user who is the subject of the event, or is in the channel of the event
|
// Only report events to a user who is the subject of the event, or is in the channel of the event
|
||||||
|
|||||||
10
i18n/en.json
10
i18n/en.json
@@ -655,6 +655,14 @@
|
|||||||
"id": "api.oauth.revoke_access_token.get.app_error",
|
"id": "api.oauth.revoke_access_token.get.app_error",
|
||||||
"translation": "Error getting access token from DB before deletion"
|
"translation": "Error getting access token from DB before deletion"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "api.post.check_for_out_of_channel_mentions.message.one",
|
||||||
|
"translation": "{{.Username}} was mentioned, but they do not belong to this channel."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "api.post.check_for_out_of_channel_mentions.message.multiple",
|
||||||
|
"translation": "{{.Usernames}} and {{.LastUsername}} were mentioned, but they do not belong to this channel."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "api.post.create_post.bad_filename.error",
|
"id": "api.post.create_post.bad_filename.error",
|
||||||
"translation": "Bad filename discarded, filename=%v"
|
"translation": "Bad filename discarded, filename=%v"
|
||||||
@@ -3459,4 +3467,4 @@
|
|||||||
"id": "web.watcher_fail.error",
|
"id": "web.watcher_fail.error",
|
||||||
"translation": "Failed to add directory to watcher %v"
|
"translation": "Failed to add directory to watcher %v"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
10
i18n/es.json
10
i18n/es.json
@@ -655,6 +655,14 @@
|
|||||||
"id": "api.oauth.revoke_access_token.get.app_error",
|
"id": "api.oauth.revoke_access_token.get.app_error",
|
||||||
"translation": "Error obteniendo el token de acceso desde la BD antes de ser eliminado"
|
"translation": "Error obteniendo el token de acceso desde la BD antes de ser eliminado"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "api.post.check_for_out_of_channel_mentions.message.one",
|
||||||
|
"translation": "{ .Username } was mentioned, but they do not belong to this channel."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "api.post.check_for_out_of_channel_mentions.message.multiple",
|
||||||
|
"translation": "{ .Usernames } and { .LastUsername} were mentioned, but they do not belong to this channel."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "api.post.create_post.bad_filename.error",
|
"id": "api.post.create_post.bad_filename.error",
|
||||||
"translation": "Nombre errado de archivo descartado, archivo=%v"
|
"translation": "Nombre errado de archivo descartado, archivo=%v"
|
||||||
@@ -3459,4 +3467,4 @@
|
|||||||
"id": "web.watcher_fail.error",
|
"id": "web.watcher_fail.error",
|
||||||
"translation": "Falla al agregar el directorio a ser vigilado %v"
|
"translation": "Falla al agregar el directorio a ser vigilado %v"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const (
|
|||||||
ACTION_USER_ADDED = "user_added"
|
ACTION_USER_ADDED = "user_added"
|
||||||
ACTION_USER_REMOVED = "user_removed"
|
ACTION_USER_REMOVED = "user_removed"
|
||||||
ACTION_PREFERENCE_CHANGED = "preference_changed"
|
ACTION_PREFERENCE_CHANGED = "preference_changed"
|
||||||
|
ACTION_EPHEMERAL_MESSAGE = "ephemeral_message"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
POST_SYSTEM_MESSAGE_PREFIX = "system_"
|
POST_SYSTEM_MESSAGE_PREFIX = "system_"
|
||||||
POST_DEFAULT = ""
|
POST_DEFAULT = ""
|
||||||
POST_SLACK_ATTACHMENT = "slack_attachment"
|
POST_SLACK_ATTACHMENT = "slack_attachment"
|
||||||
POST_JOIN_LEAVE = "system_join_leave"
|
POST_JOIN_LEAVE = "system_join_leave"
|
||||||
POST_HEADER_CHANGE = "system_header_change"
|
POST_HEADER_CHANGE = "system_header_change"
|
||||||
|
POST_OUT_OF_CHANNEL_MENTION = "system_out_of_channel_mention"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Post struct {
|
type Post struct {
|
||||||
@@ -33,6 +34,7 @@ type Post struct {
|
|||||||
Hashtags string `json:"hashtags"`
|
Hashtags string `json:"hashtags"`
|
||||||
Filenames StringArray `json:"filenames"`
|
Filenames StringArray `json:"filenames"`
|
||||||
PendingPostId string `json:"pending_post_id" db:"-"`
|
PendingPostId string `json:"pending_post_id" db:"-"`
|
||||||
|
Ephemeral bool `json:"ephemeral" db:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Post) ToJson() string {
|
func (o *Post) ToJson() string {
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ class SocketStoreClass extends EventEmitter {
|
|||||||
handleMessage(msg) {
|
handleMessage(msg) {
|
||||||
switch (msg.action) {
|
switch (msg.action) {
|
||||||
case SocketEvents.POSTED:
|
case SocketEvents.POSTED:
|
||||||
|
case SocketEvents.EPHEMERAL_MESSAGE:
|
||||||
handleNewPostEvent(msg, this.translations);
|
handleNewPostEvent(msg, this.translations);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ export default {
|
|||||||
USER_ADDED: 'user_added',
|
USER_ADDED: 'user_added',
|
||||||
USER_REMOVED: 'user_removed',
|
USER_REMOVED: 'user_removed',
|
||||||
TYPING: 'typing',
|
TYPING: 'typing',
|
||||||
PREFERENCE_CHANGED: 'preference_changed'
|
PREFERENCE_CHANGED: 'preference_changed',
|
||||||
|
EPHEMERAL_MESSAGE: 'ephemeral_message'
|
||||||
},
|
},
|
||||||
|
|
||||||
//SPECIAL_MENTIONS: ['all', 'channel'],
|
//SPECIAL_MENTIONS: ['all', 'channel'],
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user