From 0c919d9146fb2616cc48eca073d8d48e626d1e00 Mon Sep 17 00:00:00 2001 From: Denis Arh Date: Sat, 27 Apr 2019 19:31:45 +0200 Subject: [PATCH] Implements /search/threads --- api/messaging/spec.json | 22 ++++++++++++ api/messaging/spec/search.json | 22 ++++++++++++ docs/messaging/README.md | 17 +++++++++ messaging/rest/handlers/search.go | 23 ++++++++++++ messaging/rest/request/search.go | 58 +++++++++++++++++++++++++++++++ messaging/rest/search.go | 9 +++++ 6 files changed, 151 insertions(+) diff --git a/api/messaging/spec.json b/api/messaging/spec.json index 68dfa93c7..6d451d098 100644 --- a/api/messaging/spec.json +++ b/api/messaging/spec.json @@ -858,6 +858,28 @@ } ] } + }, + { + "method": "GET", + "name": "threads", + "path": "/threads", + "title": "Search for threads", + "parameters": { + "get": [ + { + "name": "channelID", + "type": "[]uint64", + "required": false, + "title": "Filter by channels" + }, + { + "name": "limit", + "type": "uint", + "required": false, + "title": "Max number of messages" + } + ] + } } ] }, diff --git a/api/messaging/spec/search.json b/api/messaging/spec/search.json index 0916423fa..acaf7792d 100644 --- a/api/messaging/spec/search.json +++ b/api/messaging/spec/search.json @@ -94,6 +94,28 @@ } ] } + }, + { + "Name": "threads", + "Method": "GET", + "Title": "Search for threads", + "Path": "/threads", + "Parameters": { + "get": [ + { + "name": "channelID", + "required": false, + "title": "Filter by channels", + "type": "[]uint64" + }, + { + "name": "limit", + "required": false, + "title": "Max number of messages", + "type": "uint" + } + ] + } } ] } \ No newline at end of file diff --git a/docs/messaging/README.md b/docs/messaging/README.md index 6ad241e4f..966cb8dea 100644 --- a/docs/messaging/README.md +++ b/docs/messaging/README.md @@ -561,6 +561,7 @@ The following event types may be sent with a message event: | Method | Endpoint | Purpose | | ------ | -------- | ------- | | `GET` | `/search/messages` | Search for messages | +| `GET` | `/search/threads` | Search for threads | ## Search for messages @@ -587,6 +588,22 @@ The following event types may be sent with a message event: | limit | uint | GET | Max number of messages | N/A | NO | | query | string | GET | Search query | N/A | NO | +## Search for threads + +#### Method + +| URI | Protocol | Method | Authentication | +| --- | -------- | ------ | -------------- | +| `/search/threads` | HTTP/S | GET | Client ID, Session ID | + +#### Request parameters + +| Parameter | Type | Method | Description | Default | Required? | +| --------- | ---- | ------ | ----------- | ------- | --------- | +| channelID | []uint64 | GET | Filter by channels | N/A | NO | +| limit | uint | GET | Max number of messages | N/A | NO | +| query | string | GET | Search query | N/A | NO | + --- diff --git a/messaging/rest/handlers/search.go b/messaging/rest/handlers/search.go index a9c67fabb..0ceb72296 100644 --- a/messaging/rest/handlers/search.go +++ b/messaging/rest/handlers/search.go @@ -29,11 +29,13 @@ import ( // Internal API interface type SearchAPI interface { Messages(context.Context, *request.SearchMessages) (interface{}, error) + Threads(context.Context, *request.SearchThreads) (interface{}, error) } // HTTP API interface type Search struct { Messages func(http.ResponseWriter, *http.Request) + Threads func(http.ResponseWriter, *http.Request) } func NewSearch(sh SearchAPI) *Search { @@ -58,6 +60,26 @@ func NewSearch(sh SearchAPI) *Search { return } }, + Threads: func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + params := request.NewSearchThreads() + if err := params.Fill(r); err != nil { + resputil.JSON(w, err) + return + } + if value, err := sh.Threads(r.Context(), params); err != nil { + resputil.JSON(w, err) + return + } else { + switch fn := value.(type) { + case func(http.ResponseWriter, *http.Request): + fn(w, r) + return + } + resputil.JSON(w, value) + return + } + }, } } @@ -65,5 +87,6 @@ func (sh *Search) MountRoutes(r chi.Router, middlewares ...func(http.Handler) ht r.Group(func(r chi.Router) { r.Use(middlewares...) r.Get("/search/messages", sh.Messages) + r.Get("/search/threads", sh.Threads) }) } diff --git a/messaging/rest/request/search.go b/messaging/rest/request/search.go index 5a8db80bc..192dada24 100644 --- a/messaging/rest/request/search.go +++ b/messaging/rest/request/search.go @@ -133,3 +133,61 @@ func (sReq *SearchMessages) Fill(r *http.Request) (err error) { } var _ RequestFiller = NewSearchMessages() + +// Search threads request parameters +type SearchThreads struct { + ChannelID []uint64 `json:",string"` + Limit uint + Query string +} + +func NewSearchThreads() *SearchThreads { + return &SearchThreads{} +} + +func (sReq *SearchThreads) Fill(r *http.Request) (err error) { + if strings.ToLower(r.Header.Get("content-type")) == "application/json" { + err = json.NewDecoder(r.Body).Decode(sReq) + + switch { + case err == io.EOF: + err = nil + case err != nil: + return errors.Wrap(err, "error parsing http request body") + } + } + + if err = r.ParseForm(); err != nil { + return err + } + + get := map[string]string{} + post := map[string]string{} + urlQuery := r.URL.Query() + for name, param := range urlQuery { + get[name] = string(param[0]) + } + postVars := r.Form + for name, param := range postVars { + post[name] = string(param[0]) + } + + if val, ok := urlQuery["channelID[]"]; ok { + sReq.ChannelID = parseUInt64A(val) + } else if val, ok = urlQuery["channelID"]; ok { + sReq.ChannelID = parseUInt64A(val) + } + + if val, ok := get["limit"]; ok { + + sReq.Limit = parseUint(val) + } + if val, ok := get["query"]; ok { + + sReq.Query = val + } + + return err +} + +var _ RequestFiller = NewSearchThreads() diff --git a/messaging/rest/search.go b/messaging/rest/search.go index f37d1267a..6010dbcfc 100644 --- a/messaging/rest/search.go +++ b/messaging/rest/search.go @@ -45,6 +45,15 @@ func (ctrl *Search) Messages(ctx context.Context, r *request.SearchMessages) (in })) } +func (ctrl *Search) Threads(ctx context.Context, r *request.SearchThreads) (interface{}, error) { + return ctrl.wrapSet(ctx)(ctrl.svc.msg.With(ctx).FindThreads(&types.MessageFilter{ + ChannelID: r.ChannelID, + Limit: r.Limit, + + Query: r.Query, + })) +} + func (ctrl *Search) wrapSet(ctx context.Context) func(mm types.MessageSet, err error) (*outgoing.MessageSet, error) { return func(mm types.MessageSet, err error) (*outgoing.MessageSet, error) { if err != nil {