From d47457a67cc4acb2e94693d99c5a40e73e322a81 Mon Sep 17 00:00:00 2001 From: nxshock Date: Sat, 3 Aug 2019 19:47:33 +0500 Subject: [PATCH] Add basic implementation of Post publicRooms method --- STATUS.md | 2 +- internal/backend.go | 2 +- internal/backends/memory/backend.go | 8 +- internal/handlers.go | 100 ++++++++++++--------- internal/models/publicrooms/publicrooms.go | 14 ++- 5 files changed, 76 insertions(+), 50 deletions(-) diff --git a/STATUS.md b/STATUS.md index 71864c0..f787742 100644 --- a/STATUS.md +++ b/STATUS.md @@ -114,7 +114,7 @@ Implemented from [Client-Server API](https://matrix.org/docs/spec/client_server/ - [x] [10.5.2 PUT /_matrix/client/r0/directory/list/room/{roomId}](https://matrix.org/docs/spec/client_server/latest#put-matrix-client-r0-directory-list-room-roomid) - [x] [10.5.3 GET /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-publicrooms) -- [ ] [10.5.4 POST /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-publicrooms) +- [x] [10.5.4 POST /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-publicrooms) ## [11 User Data](https://matrix.org/docs/spec/client_server/latest#user-data) diff --git a/internal/backend.go b/internal/backend.go index 14bdfbf..a89a7db 100644 --- a/internal/backend.go +++ b/internal/backend.go @@ -15,7 +15,7 @@ type Backend interface { GetUserByName(userName string) User GetRoomByID(id string) Room Sync(token string, request sync.SyncRequest) (response *sync.SyncReply, err models.ApiError) - PublicRooms() []Room + PublicRooms(filter string) []Room ValidateUsernameFunc() func(string) error } diff --git a/internal/backends/memory/backend.go b/internal/backends/memory/backend.go index 64c9391..7696625 100644 --- a/internal/backends/memory/backend.go +++ b/internal/backends/memory/backend.go @@ -4,6 +4,7 @@ import ( "fmt" "regexp" "sort" + "strings" "sync" "github.com/signaller-matrix/signaller/internal" @@ -125,14 +126,17 @@ func (backend *Backend) GetUserByName(userName string) internal.User { return nil } -func (backend *Backend) PublicRooms() []internal.Room { +func (backend *Backend) PublicRooms(filter string) []internal.Room { backend.mutex.Lock() defer backend.mutex.Unlock() var rooms []internal.Room for _, room := range backend.rooms { - if room.State() == createroom.PublicChat { + if room.State() == createroom.PublicChat && + (strings.Contains(room.Name(), filter) || + strings.Contains(room.Topic(), filter) || + strings.Contains(room.AliasName(), filter)) { rooms = append(rooms, room) } } diff --git a/internal/handlers.go b/internal/handlers.go index f55d87c..a5884ca 100644 --- a/internal/handlers.go +++ b/internal/handlers.go @@ -412,54 +412,68 @@ func listRoomHandler(w http.ResponseWriter, r *http.Request) { // https://matrix.org/docs/spec/client_server/latest#id335 func publicRoomsHandler(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodGet: - var request publicrooms.Request - err := getRequest(r, &request) - if err != nil { - errorResponse(w, models.M_BAD_JSON, http.StatusBadRequest, err.Error()) + if r.Method != http.MethodGet && r.Method != http.MethodPost { + errorResponse(w, models.M_UNKNOWN, http.StatusBadRequest, "wrong method: "+r.Method) + return + } + + var request publicrooms.Request + err := getRequest(r, &request) + if err != nil { + errorResponse(w, models.M_BAD_JSON, http.StatusBadRequest, err.Error()) + return + } + + if request.Limit <= 0 { + request.Limit = 50 // TODO: move to const + } + + if r.Method == http.MethodPost { + token := getTokenFromResponse(r) + if token == "" { + errorResponse(w, models.M_FORBIDDEN, http.StatusForbidden, "") return } - if request.Limit <= 0 { - request.Limit = 50 // TODO: move to const + user := currServer.Backend.GetUserByToken(token) + if user == nil { + errorResponse(w, models.M_UNKNOWN_TOKEN, http.StatusBadRequest, "") + return } - - chunks := roomsToPublicRoomsChunks(currServer.Backend.PublicRooms()) - - var response publicrooms.Response - - // TODO: test and rewrite this code - if request.Since == "" { - if request.Limit >= len(chunks) { - response.Chunk = chunks - // TODO: should fill response.TotalRoomCountEstimate? - } else { - response.Chunk = chunks[:request.Limit] - response.NextBatch = strconv.Itoa(request.Limit + 1) - response.TotalRoomCountEstimate = len(chunks) - } - } else { - response.PrevBatch = "0" - - from, err := strconv.Atoi(request.Since) - if err != nil { - errorResponse(w, models.M_INVALID_PARAM, http.StatusBadRequest, "Wrong Since field specified") // TODO: check code - return - } - if len(chunks) >= from { - if request.Limit >= len(chunks) { - response.Chunk = chunks[from : from+request.Limit] - } else { - response.Chunk = chunks[from:] - } - } - } - sendJsonResponse(w, http.StatusOK, response) - case http.MethodPost: // TODO: implement - default: - errorResponse(w, models.M_UNKNOWN, http.StatusBadRequest, "wrong method: "+r.Method) } + + publicRooms := currServer.Backend.PublicRooms(request.Filter.GenericSearchTerm) // TODO: make Post request as User method + chunks := roomsToPublicRoomsChunks(publicRooms) + + var response publicrooms.Response + + // TODO: test and rewrite this code + if request.Since == "" { + if request.Limit >= len(chunks) { + response.Chunk = chunks + // TODO: should fill response.TotalRoomCountEstimate? + } else { + response.Chunk = chunks[:request.Limit] + response.NextBatch = strconv.Itoa(request.Limit + 1) + response.TotalRoomCountEstimate = len(chunks) + } + } else { + response.PrevBatch = "0" + + from, err := strconv.Atoi(request.Since) + if err != nil { + errorResponse(w, models.M_INVALID_PARAM, http.StatusBadRequest, "Wrong Since field specified") // TODO: check code + return + } + if len(chunks) >= from { + if request.Limit >= len(chunks) { + response.Chunk = chunks[from : from+request.Limit] + } else { + response.Chunk = chunks[from:] + } + } + } + sendJsonResponse(w, http.StatusOK, response) } func sendJsonResponse(w http.ResponseWriter, httpStatus int, data interface{}) error { diff --git a/internal/models/publicrooms/publicrooms.go b/internal/models/publicrooms/publicrooms.go index 47b936a..bcc1bc4 100644 --- a/internal/models/publicrooms/publicrooms.go +++ b/internal/models/publicrooms/publicrooms.go @@ -1,9 +1,13 @@ package publicrooms +// Merged request for Get and Post methods type Request struct { - Limit int `json:"limit"` // Limit the number of results returned. - Since string `json:"since"` // A pagination token from a previous request, allowing clients to get the next (or previous) batch of rooms. The direction of pagination is specified solely by which token is supplied, rather than via an explicit flag. - Server string `json:"server"` // The server to fetch the public room lists from. Defaults to the local server. + Limit int `json:"limit"` // Limit the number of results returned. + Since string `json:"since"` // A pagination token from a previous request, allowing clients to get the next (or previous) batch of rooms. The direction of pagination is specified solely by which token is supplied, rather than via an explicit flag. + Server string `json:"server"` // The server to fetch the public room lists from. Defaults to the local server. + Filter Filter `json:"filter"` // Filter to apply to the results. + IncludeAllNetworks bool `json:"include_all_networks"` // Whether or not to include all known networks/protocols from application services on the homeserver. Defaults to false. + ThirdPartyInstanceID string `json:"third_party_instance_id"` // The specific third party network/protocol to request from the homeserver. Can only be used if include_all_networks is false. } type Response struct { @@ -24,3 +28,7 @@ type PublicRoomsChunk struct { GuestCanJoin bool `json:"guest_can_join"` // Required. Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user. AvatarURL string `json:"avatar_url,omitempty"` // The URL for the room's avatar, if one is set. } + +type Filter struct { + GenericSearchTerm string `json:"generic_search_term,omitempty"` // A string to search for in the room metadata, e.g. name, topic, canonical alias etc. (Optional). +}