mirror of
https://github.com/signaller-matrix/signaller.git
synced 2024-11-09 12:11:03 +00:00
Add basic implementation of PublicRooms method
This commit is contained in:
parent
823ab7e100
commit
782c328e3d
@ -113,7 +113,7 @@ Implemented from [Client-Server API](https://matrix.org/docs/spec/client_server/
|
||||
- [x] [10.5.1 GET /_matrix/client/r0/directory/list/room/{roomId}](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-directory-list-room-roomid)
|
||||
- [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)
|
||||
|
||||
- [ ] [10.5.3 GET /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-publicrooms)
|
||||
- [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)
|
||||
|
||||
## [11 User Data](https://matrix.org/docs/spec/client_server/latest#user-data)
|
||||
|
@ -15,6 +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
|
||||
}
|
||||
|
||||
type Room interface {
|
||||
@ -26,6 +27,9 @@ type Room interface {
|
||||
Topic() string
|
||||
Events() []rooms.Event
|
||||
Visibility() createroom.VisibilityType
|
||||
WorldReadable() bool
|
||||
GuestCanJoin() bool
|
||||
AvatarURL() string
|
||||
State() createroom.Preset
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/nxshock/signaller/internal/models/createroom"
|
||||
|
||||
"github.com/nxshock/signaller/internal"
|
||||
"github.com/nxshock/signaller/internal/models"
|
||||
mSync "github.com/nxshock/signaller/internal/models/sync"
|
||||
@ -111,3 +114,20 @@ func (backend *Backend) GetUserByName(userName string) internal.User {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (backend *Backend) PublicRooms() []internal.Room {
|
||||
backend.mutex.Lock()
|
||||
defer backend.mutex.Unlock()
|
||||
|
||||
var rooms []internal.Room
|
||||
|
||||
for _, room := range backend.rooms {
|
||||
if room.State() == createroom.PublicChat {
|
||||
rooms = append(rooms, room)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(BySize(rooms))
|
||||
|
||||
return rooms
|
||||
}
|
||||
|
@ -15,6 +15,9 @@ type Room struct {
|
||||
name string
|
||||
topic string
|
||||
state createroom.Preset
|
||||
worldReadable bool
|
||||
guestCanJoin bool
|
||||
avatarURL string
|
||||
|
||||
creator internal.User
|
||||
joined []internal.User
|
||||
@ -93,3 +96,24 @@ func (room *Room) State() createroom.Preset {
|
||||
|
||||
return room.state
|
||||
}
|
||||
|
||||
func (room *Room) WorldReadable() bool {
|
||||
room.mutex.RLock()
|
||||
defer room.mutex.RUnlock()
|
||||
|
||||
return room.worldReadable
|
||||
}
|
||||
|
||||
func (room *Room) GuestCanJoin() bool {
|
||||
room.mutex.RLock()
|
||||
defer room.mutex.RUnlock()
|
||||
|
||||
return room.guestCanJoin
|
||||
}
|
||||
|
||||
func (room *Room) AvatarURL() string {
|
||||
room.mutex.RLock()
|
||||
defer room.mutex.RUnlock()
|
||||
|
||||
return room.avatarURL
|
||||
}
|
||||
|
11
internal/backends/memory/roomsort.go
Normal file
11
internal/backends/memory/roomsort.go
Normal file
@ -0,0 +1,11 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"github.com/nxshock/signaller/internal"
|
||||
)
|
||||
|
||||
type BySize []internal.Room
|
||||
|
||||
func (a BySize) Len() int { return len(a) }
|
||||
func (a BySize) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a BySize) Less(i, j int) bool { return len(a[i].Users()) > len(a[j].Users()) }
|
@ -8,21 +8,19 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/nxshock/signaller/internal/models/registeravailable"
|
||||
|
||||
"github.com/nxshock/signaller/internal/models/devices"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/nxshock/signaller/internal/models/common"
|
||||
|
||||
"github.com/nxshock/signaller/internal/models"
|
||||
"github.com/nxshock/signaller/internal/models/capabilities"
|
||||
"github.com/nxshock/signaller/internal/models/common"
|
||||
"github.com/nxshock/signaller/internal/models/devices"
|
||||
"github.com/nxshock/signaller/internal/models/joinedrooms"
|
||||
"github.com/nxshock/signaller/internal/models/listroom"
|
||||
login "github.com/nxshock/signaller/internal/models/login"
|
||||
"github.com/nxshock/signaller/internal/models/password"
|
||||
"github.com/nxshock/signaller/internal/models/publicrooms"
|
||||
register "github.com/nxshock/signaller/internal/models/register"
|
||||
"github.com/nxshock/signaller/internal/models/registeravailable"
|
||||
mSync "github.com/nxshock/signaller/internal/models/sync"
|
||||
"github.com/nxshock/signaller/internal/models/versions"
|
||||
"github.com/nxshock/signaller/internal/models/whoami"
|
||||
@ -412,6 +410,58 @@ 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())
|
||||
return
|
||||
}
|
||||
|
||||
if request.Limit <= 0 {
|
||||
request.Limit = 50 // TODO: move to const
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func sendJsonResponse(w http.ResponseWriter, httpStatus int, data interface{}) error {
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
|
26
internal/models/publicrooms/publicrooms.go
Normal file
26
internal/models/publicrooms/publicrooms.go
Normal file
@ -0,0 +1,26 @@
|
||||
package publicrooms
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Chunk []PublicRoomsChunk `json:"chunk"` // A paginated chunk of public rooms.
|
||||
NextBatch string `json:"next_batch,omitempty"` // A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.
|
||||
PrevBatch string `json:"prev_batch,omitempty"` // A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.
|
||||
TotalRoomCountEstimate int `json:"total_room_count_estimate,omitempty"` // An estimate on the total number of public rooms, if the server has an estimate.
|
||||
}
|
||||
|
||||
type PublicRoomsChunk struct {
|
||||
Aliases []string `json:"aliases,omitempty"` // Aliases of the room. May be empty.
|
||||
CanonicalAlias string `json:"canonical_alias,omitempty"` // The canonical alias of the room, if any.
|
||||
Name string `json:"name,omitempty"` // The name of the room, if any.
|
||||
NumJoinedMembers int `json:"num_joined_members"` // Required. The number of members joined to the room.
|
||||
RoomID string `json:"room_id"` // Required. The ID of the room.
|
||||
Topic string `json:"topic,omitempty"` // The topic of the room, if any.
|
||||
WorldReadable bool `json:"world_readable"` // Required. Whether the room may be viewed by guest users without joining.
|
||||
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.
|
||||
}
|
@ -39,6 +39,7 @@ func NewServer(port int) (*Server, error) {
|
||||
router.HandleFunc("/_matrix/client/r0/directory/list/room/{roomID}", listRoomHandler)
|
||||
router.HandleFunc("/_matrix/client/r0/rooms/{roomId}/leave", leaveRoomHandler)
|
||||
router.HandleFunc("/_matrix/client/r0/register/available", registerAvailableHandler)
|
||||
router.HandleFunc("/_matrix/client/r0/publicRooms", publicRoomsHandler)
|
||||
router.HandleFunc("/", RootHandler)
|
||||
|
||||
if port <= 0 || port > 65535 {
|
||||
|
24
internal/utils.go
Normal file
24
internal/utils.go
Normal file
@ -0,0 +1,24 @@
|
||||
package internal
|
||||
|
||||
import "github.com/nxshock/signaller/internal/models/publicrooms"
|
||||
|
||||
func roomsToPublicRoomsChunks(rooms []Room) []publicrooms.PublicRoomsChunk {
|
||||
var chunks []publicrooms.PublicRoomsChunk
|
||||
|
||||
for _, room := range rooms {
|
||||
chunk := publicrooms.PublicRoomsChunk{
|
||||
// TODO: Aliases:
|
||||
CanonicalAlias: room.AliasName(),
|
||||
Name: room.Name(),
|
||||
NumJoinedMembers: len(room.Users()),
|
||||
RoomID: room.ID(),
|
||||
Topic: room.Topic(),
|
||||
WorldReadable: room.WorldReadable(),
|
||||
GuestCanJoin: room.GuestCanJoin(),
|
||||
AvatarURL: room.AvatarURL()}
|
||||
|
||||
chunks = append(chunks, chunk)
|
||||
}
|
||||
|
||||
return chunks
|
||||
}
|
Loading…
Reference in New Issue
Block a user