diff options
Diffstat (limited to 'model')
-rw-r--r-- | model/client.go | 37 | ||||
-rw-r--r-- | model/post.go | 1 | ||||
-rw-r--r-- | model/reaction.go | 78 | ||||
-rw-r--r-- | model/reaction_test.go | 64 | ||||
-rw-r--r-- | model/websocket_message.go | 2 |
5 files changed, 182 insertions, 0 deletions
diff --git a/model/client.go b/model/client.go index 631de9c56..f782940d8 100644 --- a/model/client.go +++ b/model/client.go @@ -2102,6 +2102,7 @@ func (c *Client) DeleteEmoji(id string) (bool, *AppError) { if r, err := c.DoApiPost(c.GetEmojiRoute()+"/delete", MapToJson(data)); err != nil { return false, err } else { + defer closeBody(r) c.fillInExtraProperties(r) return c.CheckStatusOK(r), nil } @@ -2132,6 +2133,7 @@ func (c *Client) UploadCertificateFile(data []byte, contentType string) *AppErro return AppErrorFromJson(rp.Body) } else { defer closeBody(rp) + c.fillInExtraProperties(rp) return nil } } @@ -2143,6 +2145,7 @@ func (c *Client) RemoveCertificateFile(filename string) *AppError { return err } else { defer closeBody(r) + c.fillInExtraProperties(r) return nil } } @@ -2154,6 +2157,7 @@ func (c *Client) SamlCertificateStatus(filename string) (map[string]interface{}, return nil, err } else { defer closeBody(r) + c.fillInExtraProperties(r) return StringInterfaceFromJson(r.Body), nil } } @@ -2182,3 +2186,36 @@ func (c *Client) GetFileInfosForPost(channelId string, postId string, etag strin return FileInfosFromJson(r.Body), nil } } + +// Saves an emoji reaction for a post in the given channel. Returns the saved reaction if successful, otherwise returns an AppError. +func (c *Client) SaveReaction(channelId string, reaction *Reaction) (*Reaction, *AppError) { + if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions/save", reaction.PostId), reaction.ToJson()); err != nil { + return nil, err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return ReactionFromJson(r.Body), nil + } +} + +// Removes an emoji reaction for a post in the given channel. Returns nil if successful, otherwise returns an AppError. +func (c *Client) DeleteReaction(channelId string, reaction *Reaction) *AppError { + if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions/delete", reaction.PostId), reaction.ToJson()); err != nil { + return err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return nil + } +} + +// Lists all emoji reactions made for the given post in the given channel. Returns a list of Reactions if successful, otherwise returns an AppError. +func (c *Client) ListReactions(channelId string, postId string) ([]*Reaction, *AppError) { + if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions", postId), "", ""); err != nil { + return nil, err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return ReactionsFromJson(r.Body), nil + } +} diff --git a/model/post.go b/model/post.go index da14b650f..b5dcc4539 100644 --- a/model/post.go +++ b/model/post.go @@ -38,6 +38,7 @@ type Post struct { Filenames StringArray `json:"filenames,omitempty"` // Deprecated, do not use this field any more FileIds StringArray `json:"file_ids,omitempty"` PendingPostId string `json:"pending_post_id" db:"-"` + HasReactions bool `json:"has_reactions,omitempty"` } func (o *Post) ToJson() string { diff --git a/model/reaction.go b/model/reaction.go new file mode 100644 index 000000000..afbdd1e88 --- /dev/null +++ b/model/reaction.go @@ -0,0 +1,78 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type Reaction struct { + UserId string `json:"user_id"` + PostId string `json:"post_id"` + EmojiName string `json:"emoji_name"` + CreateAt int64 `json:"create_at"` +} + +func (o *Reaction) ToJson() string { + if b, err := json.Marshal(o); err != nil { + return "" + } else { + return string(b) + } +} + +func ReactionFromJson(data io.Reader) *Reaction { + var o Reaction + + if err := json.NewDecoder(data).Decode(&o); err != nil { + return nil + } else { + return &o + } +} + +func ReactionsToJson(o []*Reaction) string { + if b, err := json.Marshal(o); err != nil { + return "" + } else { + return string(b) + } +} + +func ReactionsFromJson(data io.Reader) []*Reaction { + var o []*Reaction + + if err := json.NewDecoder(data).Decode(&o); err != nil { + return nil + } else { + return o + } +} + +func (o *Reaction) IsValid() *AppError { + if len(o.UserId) != 26 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.user_id.app_error", nil, "user_id="+o.UserId) + } + + if len(o.PostId) != 26 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.post_id.app_error", nil, "post_id="+o.PostId) + } + + if len(o.EmojiName) == 0 || len(o.EmojiName) > 64 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.emoji_name.app_error", nil, "emoji_name="+o.EmojiName) + } + + if o.CreateAt == 0 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.create_at.app_error", nil, "") + } + + return nil +} + +func (o *Reaction) PreSave() { + if o.CreateAt == 0 { + o.CreateAt = GetMillis() + } +} diff --git a/model/reaction_test.go b/model/reaction_test.go new file mode 100644 index 000000000..da73f477a --- /dev/null +++ b/model/reaction_test.go @@ -0,0 +1,64 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "strings" + "testing" +) + +func TestReactionIsValid(t *testing.T) { + reaction := Reaction{ + UserId: NewId(), + PostId: NewId(), + EmojiName: "emoji", + CreateAt: GetMillis(), + } + + if err := reaction.IsValid(); err != nil { + t.Fatal(err) + } + + reaction.UserId = "" + if err := reaction.IsValid(); err == nil { + t.Fatal("user id should be invalid") + } + + reaction.UserId = "1234garbage" + if err := reaction.IsValid(); err == nil { + t.Fatal("user id should be invalid") + } + + reaction.UserId = NewId() + reaction.PostId = "" + if err := reaction.IsValid(); err == nil { + t.Fatal("post id should be invalid") + } + + reaction.PostId = "1234garbage" + if err := reaction.IsValid(); err == nil { + t.Fatal("post id should be invalid") + } + + reaction.PostId = NewId() + reaction.EmojiName = "" + if err := reaction.IsValid(); err == nil { + t.Fatal("emoji name should be invalid") + } + + reaction.EmojiName = strings.Repeat("a", 65) + if err := reaction.IsValid(); err == nil { + t.Fatal("emoji name should be invalid") + } + + reaction.EmojiName = strings.Repeat("a", 64) + if err := reaction.IsValid(); err != nil { + t.Fatal(err) + } + + reaction.CreateAt = 0 + if err := reaction.IsValid(); err == nil { + t.Fatal("create at should be invalid") + } +} diff --git a/model/websocket_message.go b/model/websocket_message.go index 3fa58aeb3..c3530c038 100644 --- a/model/websocket_message.go +++ b/model/websocket_message.go @@ -27,6 +27,8 @@ const ( WEBSOCKET_EVENT_HELLO = "hello" WEBSOCKET_EVENT_WEBRTC = "webrtc" WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge" + WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added" + WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed" ) type WebSocketMessage interface { |