diff --git a/client.go b/client.go index fc290ed..7625a1c 100644 --- a/client.go +++ b/client.go @@ -372,6 +372,53 @@ func (cli *Client) Versions() (resp *RespVersions, err error) { return } +// PublicRooms returns the list of public rooms on target server. See https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-unstable-publicrooms +func (cli *Client) PublicRooms(limit int, since string, server string) (resp *RespPublicRooms, err error) { + args := map[string]string{} + + if limit != 0 { + args["limit"] = strconv.Itoa(limit) + } + if since != "" { + args["since"] = since + } + if server != "" { + args["server"] = server + } + + urlPath := cli.BuildURLWithQuery([]string{"publicRooms"}, args) + err = cli.MakeRequest("GET", urlPath, nil, &resp) + return +} + +// PublicRoomsFiltered returns a subset of PublicRooms filtered server side. +// See https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-unstable-publicrooms +func (cli *Client) PublicRoomsFiltered(limit int, since string, server string, filter string) (resp *RespPublicRooms, err error) { + content := map[string]string{} + + if limit != 0 { + content["limit"] = strconv.Itoa(limit) + } + if since != "" { + content["since"] = since + } + if filter != "" { + content["filter"] = filter + } + + var urlPath string + if server == "" { + urlPath = cli.BuildURL("publicRooms") + } else { + urlPath = cli.BuildURLWithQuery([]string{"publicRooms"}, map[string]string{ + "server": server, + }) + } + + err = cli.MakeRequest("POST", urlPath, content, &resp) + return +} + // JoinRoom joins the client to a room ID or alias. See http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-join-roomidoralias // // If serverName is specified, this will be added as a query param to instruct the homeserver to join via that server. If content is specified, it will diff --git a/client_test.go b/client_test.go index 9b7d2da..b975873 100644 --- a/client_test.go +++ b/client_test.go @@ -84,6 +84,55 @@ func TestClient_StateEvent(t *testing.T) { } } +func TestClient_PublicRooms(t *testing.T) { + cli := mockClient(func(req *http.Request) (*http.Response, error) { + if req.Method == "GET" && req.URL.Path == "/_matrix/client/r0/publicRooms" { + return &http.Response{ + StatusCode: 200, + Body: ioutil.NopCloser(bytes.NewBufferString(`{ + "chunk": [ + { + "aliases": [ + "#murrays:cheese.bar" + ], + "avatar_url": "mxc://bleeker.street/CHEDDARandBRIE", + "guest_can_join": false, + "name": "CHEESE", + "num_joined_members": 37, + "room_id": "!ol19s:bleecker.street", + "topic": "Tasty tasty cheese", + "world_readable": true + } + ], + "next_batch": "p190q", + "prev_batch": "p1902", + "total_room_count_estimate": 115 +}`)), + }, nil + } + + return nil, fmt.Errorf("unhandled URL: %s", req.URL.Path) + }) + + publicRooms, err := cli.PublicRooms(0, "", "") + + if err != nil { + t.Fatalf("PublicRooms: error, got %s", err.Error()) + } + if publicRooms.TotalRoomCountEstimate != 115 { + t.Fatalf("PublicRooms: got %d, want %d", publicRooms.TotalRoomCountEstimate, 115) + } + if len(publicRooms.Chunk) != 1 { + t.Fatalf("PublicRooms: got %d, want %d", len(publicRooms.Chunk), 1) + } + if publicRooms.Chunk[0].Name != "CHEESE" { + t.Fatalf("PublicRooms: got %s, want %s", publicRooms.Chunk[0].Name, "CHEESE") + } + if publicRooms.Chunk[0].NumJoinedMembers != 37 { + t.Fatalf("PublicRooms: got %d, want %d", publicRooms.Chunk[0].NumJoinedMembers, 37) + } +} + func mockClient(fn func(*http.Request) (*http.Response, error)) *Client { mrt := MockRoundTripper{ RT: fn, diff --git a/events.go b/events.go index edf231a..e82a6a3 100644 --- a/events.go +++ b/events.go @@ -7,15 +7,16 @@ import ( // Event represents a single Matrix event. type Event struct { - StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events. - Sender string `json:"sender"` // The user ID of the sender of the event - Type string `json:"type"` // The event type - Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server - ID string `json:"event_id"` // The unique ID of this event - RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence) - Content map[string]interface{} `json:"content"` // The JSON content of the event. - Redacts string `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event - Unsigned map[string]interface{} `json:"unsigned"` // The unsigned portions of the event, such as age and prev_content + StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events. + Sender string `json:"sender"` // The user ID of the sender of the event + Type string `json:"type"` // The event type + Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server + ID string `json:"event_id"` // The unique ID of this event + RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence) + Redacts string `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event + Unsigned map[string]interface{} `json:"unsigned"` // The unsigned portions of the event, such as age and prev_content + Content map[string]interface{} `json:"content"` // The JSON content of the event. + PrevContent map[string]interface{} `json:"prev_content,omitempty"` // The JSON prev_content of the event. } // Body returns the value of the "body" key in the event content if it is diff --git a/responses.go b/responses.go index 7a3a4ce..effb609 100644 --- a/responses.go +++ b/responses.go @@ -22,6 +22,14 @@ type RespVersions struct { Versions []string `json:"versions"` } +// RespPublicRooms is the JSON response for http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#get-matrix-client-unstable-publicrooms +type RespPublicRooms struct { + TotalRoomCountEstimate int `json:"total_room_count_estimate"` + PrevBatch string `json:"prev_batch"` + NextBatch string `json:"next_batch"` + Chunk []PublicRoom `json:"chunk"` +} + // RespJoinRoom is the JSON response for http://matrix.org/docs/spec/client_server/r0.2.0.html#post-matrix-client-r0-rooms-roomid-join type RespJoinRoom struct { RoomID string `json:"room_id"` diff --git a/room.go b/room.go index c9b2351..d1d2286 100644 --- a/room.go +++ b/room.go @@ -6,6 +6,19 @@ type Room struct { State map[string]map[string]*Event } +// PublicRoom represents the information about a public room obtainable from the room directory +type PublicRoom struct { + CanonicalAlias string `json:"canonical_alias"` + Name string `json:"name"` + WorldReadable bool `json:"world_readable"` + Topic string `json:"topic"` + NumJoinedMembers int `json:"num_joined_members"` + AvatarURL string `json:"avatar_url"` + RoomID string `json:"room_id"` + GuestCanJoin bool `json:"guest_can_join"` + Aliases []string `json:"aliases"` +} + // UpdateState updates the room's current state with the given Event. This will clobber events based // on the type/state_key combination. func (room Room) UpdateState(event *Event) {