From 3918ed6c589a19bd385a6e566f07dc14d7484c49 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Wed, 24 Jan 2018 08:50:11 -0500 Subject: Add GET /emojis/name/{emoji_name} API endpoint (#8142) --- api4/api.go | 6 ++++-- api4/emoji.go | 16 ++++++++++++++++ api4/emoji_test.go | 27 +++++++++++++++++++++++++++ app/emoji.go | 16 ++++++++++++++++ model/client4.go | 16 +++++++++++++++- store/sqlstore/emoji_store.go | 4 ++++ 6 files changed, 82 insertions(+), 3 deletions(-) diff --git a/api4/api.go b/api4/api.go index 90c9d0df7..580bd8c58 100644 --- a/api4/api.go +++ b/api4/api.go @@ -96,8 +96,9 @@ type Routes struct { Reactions *mux.Router // 'api/v4/reactions' - Emojis *mux.Router // 'api/v4/emoji' - Emoji *mux.Router // 'api/v4/emoji/{emoji_id:[A-Za-z0-9]+}' + Emojis *mux.Router // 'api/v4/emoji' + Emoji *mux.Router // 'api/v4/emoji/{emoji_id:[A-Za-z0-9]+}' + EmojiByName *mux.Router // 'api/v4/emoji/name/{emoji_name:[A-Za-z0-9_-\.]+}' ReactionByNameForPostForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/posts/{post_id:[A-Za-z0-9]+}/reactions/{emoji_name:[A-Za-z0-9_-+]+}' @@ -185,6 +186,7 @@ func Init(a *app.App, root *mux.Router, full bool) *API { api.BaseRoutes.Emojis = api.BaseRoutes.ApiRoot.PathPrefix("/emoji").Subrouter() api.BaseRoutes.Emoji = api.BaseRoutes.ApiRoot.PathPrefix("/emoji/{emoji_id:[A-Za-z0-9]+}").Subrouter() + api.BaseRoutes.EmojiByName = api.BaseRoutes.Emojis.PathPrefix("/name/{emoji_name:[A-Za-z0-9\\_\\-\\+]+}").Subrouter() api.BaseRoutes.ReactionByNameForPostForUser = api.BaseRoutes.PostForUser.PathPrefix("/reactions/{emoji_name:[A-Za-z0-9\\_\\-\\+]+}").Subrouter() diff --git a/api4/emoji.go b/api4/emoji.go index 30d59125b..ae4a35dd5 100644 --- a/api4/emoji.go +++ b/api4/emoji.go @@ -22,6 +22,7 @@ func (api *API) InitEmoji() { api.BaseRoutes.Emojis.Handle("/autocomplete", api.ApiSessionRequired(autocompleteEmojis)).Methods("GET") api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(deleteEmoji)).Methods("DELETE") api.BaseRoutes.Emoji.Handle("", api.ApiSessionRequired(getEmoji)).Methods("GET") + api.BaseRoutes.EmojiByName.Handle("", api.ApiSessionRequired(getEmojiByName)).Methods("GET") api.BaseRoutes.Emoji.Handle("/image", api.ApiSessionRequiredTrustRequester(getEmojiImage)).Methods("GET") } @@ -142,6 +143,21 @@ func getEmoji(c *Context, w http.ResponseWriter, r *http.Request) { } } +func getEmojiByName(c *Context, w http.ResponseWriter, r *http.Request) { + c.RequireEmojiName() + if c.Err != nil { + return + } + + emoji, err := c.App.GetEmojiByName(c.Params.EmojiName) + if err != nil { + c.Err = err + return + } else { + w.Write([]byte(emoji.ToJson())) + } +} + func getEmojiImage(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireEmojiId() if c.Err != nil { diff --git a/api4/emoji_test.go b/api4/emoji_test.go index b8b093656..39da4aaef 100644 --- a/api4/emoji_test.go +++ b/api4/emoji_test.go @@ -316,6 +316,33 @@ func TestGetEmoji(t *testing.T) { CheckNotFoundStatus(t, resp) } +func TestGetEmojiByName(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + Client := th.Client + + th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableCustomEmoji = true }) + + emoji := &model.Emoji{ + CreatorId: th.BasicUser.Id, + Name: model.NewId(), + } + + newEmoji, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif") + CheckNoError(t, resp) + + emoji, resp = Client.GetEmojiByName(newEmoji.Name) + CheckNoError(t, resp) + assert.Equal(t, newEmoji.Name, emoji.Name) + + _, resp = Client.GetEmojiByName(model.NewId()) + CheckNotFoundStatus(t, resp) + + Client.Logout() + _, resp = Client.GetEmojiByName(newEmoji.Name) + CheckUnauthorizedStatus(t, resp) +} + func TestGetEmojiImage(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() diff --git a/app/emoji.go b/app/emoji.go index 2271d650d..20d4bb44d 100644 --- a/app/emoji.go +++ b/app/emoji.go @@ -148,6 +148,22 @@ func (a *App) GetEmoji(emojiId string) (*model.Emoji, *model.AppError) { } } +func (a *App) GetEmojiByName(emojiName string) (*model.Emoji, *model.AppError) { + if !*a.Config().ServiceSettings.EnableCustomEmoji { + return nil, model.NewAppError("GetEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented) + } + + if len(*a.Config().FileSettings.DriverName) == 0 { + return nil, model.NewAppError("GetEmoji", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented) + } + + if result := <-a.Srv.Store.Emoji().GetByName(emojiName); result.Err != nil { + return nil, result.Err + } else { + return result.Data.(*model.Emoji), nil + } +} + func (a *App) GetEmojiImage(emojiId string) (imageByte []byte, imageType string, err *model.AppError) { if result := <-a.Srv.Store.Emoji().Get(emojiId, true); result.Err != nil { return nil, "", result.Err diff --git a/model/client4.go b/model/client4.go index 151b5a491..0694ecbdf 100644 --- a/model/client4.go +++ b/model/client4.go @@ -282,6 +282,10 @@ func (c *Client4) GetEmojiRoute(emojiId string) string { return fmt.Sprintf(c.GetEmojisRoute()+"/%v", emojiId) } +func (c *Client4) GetEmojiByNameRoute(name string) string { + return fmt.Sprintf(c.GetEmojisRoute()+"/name/%v", name) +} + func (c *Client4) GetReactionsRoute() string { return fmt.Sprintf("/reactions") } @@ -3045,7 +3049,7 @@ func (c *Client4) DeleteEmoji(emojiId string) (bool, *Response) { } } -// GetEmoji returns a custom emoji in the system on the provided emoji id string. +// GetEmoji returns a custom emoji based on the emojiId string. func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response) { if r, err := c.DoApiGet(c.GetEmojiRoute(emojiId), ""); err != nil { return nil, BuildErrorResponse(r, err) @@ -3055,6 +3059,16 @@ func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response) { } } +// GetEmojiByName returns a custom emoji based on the name string. +func (c *Client4) GetEmojiByName(name string) (*Emoji, *Response) { + if r, err := c.DoApiGet(c.GetEmojiByNameRoute(name), ""); err != nil { + return nil, BuildErrorResponse(r, err) + } else { + defer closeBody(r) + return EmojiFromJson(r.Body), BuildResponse(r) + } +} + // GetEmojiImage returns the emoji image. func (c *Client4) GetEmojiImage(emojiId string) ([]byte, *Response) { if r, err := c.DoApiGet(c.GetEmojiRoute(emojiId)+"/image", ""); err != nil { diff --git a/store/sqlstore/emoji_store.go b/store/sqlstore/emoji_store.go index afd87b83d..971cafb6a 100644 --- a/store/sqlstore/emoji_store.go +++ b/store/sqlstore/emoji_store.go @@ -4,6 +4,7 @@ package sqlstore import ( + "database/sql" "net/http" "github.com/mattermost/mattermost-server/einterfaces" @@ -118,6 +119,9 @@ func (es SqlEmojiStore) GetByName(name string) store.StoreChannel { Name = :Name AND DeleteAt = 0`, map[string]interface{}{"Name": name}); err != nil { result.Err = model.NewAppError("SqlEmojiStore.GetByName", "store.sql_emoji.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError) + if err == sql.ErrNoRows { + result.Err.StatusCode = http.StatusNotFound + } } else { result.Data = emoji } -- cgit v1.2.3-1-g7c22