MM-11272 Added initial post metadata (#9175)
* MM-11272 Added app.PreparePostForClient * MM-11272 Added app.PreparePostListForClient * MM-11272 Added EmojiStore.GetMultipleByName * MM-11272 Added emojis to PreparePostForClient * MM-11272 Added unit tests for getting reaction counts * MM-11272 Added unit tests for TestPreparePostForClient * MM-11272 Added emojis from reactions to Post.Emojis * MM-11272 Always update post.UpdateAt when reactions change to bust cache * Fixed merge conflicts * Moved post metadata-related code into its own file * Update store mocks * Fixed typo * Add missing license headers * Updated post metadata tests when custom emojis are disabled * Fix unreliable unit tests * Fix inconsistent casing in SQL statements * Fix blank line * Invalidate store cache after making changes * Clear post cache synchronously with reactions
Этот коммит содержится в:
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -14,6 +15,8 @@ const (
|
||||
EMOJI_SORT_BY_NAME = "name"
|
||||
)
|
||||
|
||||
var EMOJI_PATTERN = regexp.MustCompile(`:[a-zA-Z0-9_-]+:`)
|
||||
|
||||
type Emoji struct {
|
||||
Id string `json:"id"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/dyatlov/go-opengraph/opengraph"
|
||||
"github.com/mattermost/mattermost-server/utils/markdown"
|
||||
)
|
||||
|
||||
@@ -78,9 +79,22 @@ type Post struct {
|
||||
Props StringInterface `json:"props"`
|
||||
Hashtags string `json:"hashtags"`
|
||||
Filenames StringArray `json:"filenames,omitempty"` // Deprecated, do not use this field any more
|
||||
FileIds StringArray `json:"file_ids,omitempty"`
|
||||
FileIds StringArray `json:"file_ids,omitempty"` // Deprecated, do not use this field any more
|
||||
PendingPostId string `json:"pending_post_id" db:"-"`
|
||||
HasReactions bool `json:"has_reactions,omitempty"`
|
||||
HasReactions bool `json:"has_reactions,omitempty"` // Deprecated, do not use this field any more
|
||||
|
||||
// Transient fields populated before sending posts to the client
|
||||
ReactionCounts ReactionCounts `json:"reaction_counts" db:"-"`
|
||||
FileInfos []*FileInfo `json:"file_infos" db:"-"`
|
||||
ImageDimensions []*PostImageDimensions `json:"image_dimensions" db:"-"`
|
||||
OpenGraphData []*opengraph.OpenGraph `json:"opengraph_data" db:"-"`
|
||||
Emojis []*Emoji `json:"emojis" db:"-"`
|
||||
}
|
||||
|
||||
type PostImageDimensions struct {
|
||||
URL string `json:"url"`
|
||||
Width int64 `json:"width"`
|
||||
Height int64 `json:"height"`
|
||||
}
|
||||
|
||||
type PostEphemeral struct {
|
||||
@@ -170,10 +184,16 @@ type PostActionIntegrationResponse struct {
|
||||
EphemeralText string `json:"ephemeral_text"`
|
||||
}
|
||||
|
||||
func (o *Post) ToJson() string {
|
||||
// Shallowly clone the a post
|
||||
func (o *Post) Clone() *Post {
|
||||
copy := *o
|
||||
return ©
|
||||
}
|
||||
|
||||
func (o *Post) ToJson() string {
|
||||
copy := o.Clone()
|
||||
copy.StripActionIntegrations()
|
||||
b, _ := json.Marshal(©)
|
||||
b, _ := json.Marshal(copy)
|
||||
return string(b)
|
||||
}
|
||||
|
||||
@@ -502,12 +522,12 @@ var markdownDestinationEscaper = strings.NewReplacer(
|
||||
// WithRewrittenImageURLs returns a new shallow copy of the post where the message has been
|
||||
// rewritten via RewriteImageURLs.
|
||||
func (o *Post) WithRewrittenImageURLs(f func(string) string) *Post {
|
||||
copy := *o
|
||||
copy := o.Clone()
|
||||
copy.Message = RewriteImageURLs(o.Message, f)
|
||||
if copy.MessageSource == "" && copy.Message != o.Message {
|
||||
copy.MessageSource = o.Message
|
||||
}
|
||||
return ©
|
||||
return copy
|
||||
}
|
||||
|
||||
func (o *PostEphemeral) ToUnsanitizedJson() string {
|
||||
|
||||
@@ -17,6 +17,8 @@ type Reaction struct {
|
||||
CreateAt int64 `json:"create_at"`
|
||||
}
|
||||
|
||||
type ReactionCounts map[string]int
|
||||
|
||||
func (o *Reaction) ToJson() string {
|
||||
b, _ := json.Marshal(o)
|
||||
return string(b)
|
||||
@@ -74,3 +76,13 @@ func (o *Reaction) PreSave() {
|
||||
o.CreateAt = GetMillis()
|
||||
}
|
||||
}
|
||||
|
||||
func CountReactions(reactions []*Reaction) ReactionCounts {
|
||||
reactionCounts := ReactionCounts{}
|
||||
|
||||
for _, reaction := range reactions {
|
||||
reactionCounts[reaction.EmojiName] += 1
|
||||
}
|
||||
|
||||
return reactionCounts
|
||||
}
|
||||
|
||||
@@ -82,3 +82,38 @@ func TestReactionIsValid(t *testing.T) {
|
||||
t.Fatal("create at should be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCountReactions(t *testing.T) {
|
||||
userId := NewId()
|
||||
userId2 := NewId()
|
||||
|
||||
reactions := []*Reaction{
|
||||
{
|
||||
UserId: userId,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId,
|
||||
EmojiName: "frowning",
|
||||
},
|
||||
{
|
||||
UserId: userId2,
|
||||
EmojiName: "smile",
|
||||
},
|
||||
{
|
||||
UserId: userId2,
|
||||
EmojiName: "neutral_face",
|
||||
},
|
||||
}
|
||||
|
||||
reactionCounts := CountReactions(reactions)
|
||||
if len(reactionCounts) != 3 {
|
||||
t.Fatal("should've received counts for 3 reactions")
|
||||
} else if reactionCounts["smile"] != 2 {
|
||||
t.Fatal("should've received 2 smile reactions")
|
||||
} else if reactionCounts["frowning"] != 1 {
|
||||
t.Fatal("should've received 1 frowning reaction")
|
||||
} else if reactionCounts["neutral_face"] != 1 {
|
||||
t.Fatal("should've received 2 neutral_face reaction")
|
||||
}
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user