mirror of
https://mau.dev/mautrix/go.git
synced 2026-03-14 14:25:53 +01:00
Improve power level stuff and state event message content
This commit is contained in:
parent
67c7c97919
commit
65f2aacf90
3 changed files with 139 additions and 37 deletions
24
client.go
24
client.go
|
|
@ -10,6 +10,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"maunium.net/go/maulogger"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
|
|
@ -17,7 +18,6 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"maunium.net/go/maulogger"
|
||||
)
|
||||
|
||||
// Client represents a Matrix client.
|
||||
|
|
@ -361,7 +361,7 @@ func (cli *Client) RegisterDummy(req *ReqRegister) (*RespRegister, error) {
|
|||
}
|
||||
}
|
||||
if res == nil {
|
||||
return nil, fmt.Errorf("registration failed: does this server support m.login.dummy?")
|
||||
return nil, fmt.Errorf("registration failed: does this server support m.login.dummy? ")
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
|
@ -461,18 +461,18 @@ func (cli *Client) SetAvatarURL(url string) (err error) {
|
|||
|
||||
// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendMessageEvent(roomID string, eventType string, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
func (cli *Client) SendMessageEvent(roomID string, eventType EventType, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
txnID := txnID()
|
||||
urlPath := cli.BuildURL("rooms", roomID, "send", eventType, txnID)
|
||||
urlPath := cli.BuildURL("rooms", roomID, "send", string(eventType), txnID)
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
return
|
||||
}
|
||||
|
||||
// SendMessageEvent sends a message event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendMassagedMessageEvent(roomID string, eventType string, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
|
||||
func (cli *Client) SendMassagedMessageEvent(roomID string, eventType EventType, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
|
||||
txnID := txnID()
|
||||
urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "send", eventType, txnID}, map[string]string{
|
||||
urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "send", string(eventType), txnID}, map[string]string{
|
||||
"ts": strconv.FormatInt(ts, 10),
|
||||
})
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
|
|
@ -481,16 +481,16 @@ func (cli *Client) SendMassagedMessageEvent(roomID string, eventType string, con
|
|||
|
||||
// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendStateEvent(roomID, eventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
urlPath := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
|
||||
func (cli *Client) SendStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}) (resp *RespSendEvent, err error) {
|
||||
urlPath := cli.BuildURL("rooms", roomID, "state", string(eventType), stateKey)
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
return
|
||||
}
|
||||
|
||||
// SendStateEvent sends a state event into a room. See http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey
|
||||
// contentJSON should be a pointer to something that can be encoded as JSON using json.Marshal.
|
||||
func (cli *Client) SendMassagedStateEvent(roomID, eventType, stateKey string, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
|
||||
urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "state", eventType, stateKey}, map[string]string{
|
||||
func (cli *Client) SendMassagedStateEvent(roomID string, eventType EventType, stateKey string, contentJSON interface{}, ts int64) (resp *RespSendEvent, err error) {
|
||||
urlPath := cli.BuildURLWithQuery([]string{"rooms", roomID, "state", string(eventType), stateKey}, map[string]string{
|
||||
"ts": strconv.FormatInt(ts, 10),
|
||||
})
|
||||
_, err = cli.MakeRequest("PUT", urlPath, contentJSON, &resp)
|
||||
|
|
@ -621,8 +621,8 @@ func (cli *Client) SetPresence(status string) (err error) {
|
|||
// StateEvent gets a single state event in a room. It will attempt to JSON unmarshal into the given "outContent" struct with
|
||||
// the HTTP response body, or return an error.
|
||||
// See http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey
|
||||
func (cli *Client) StateEvent(roomID, eventType, stateKey string, outContent interface{}) (err error) {
|
||||
u := cli.BuildURL("rooms", roomID, "state", eventType, stateKey)
|
||||
func (cli *Client) StateEvent(roomID string, eventType EventType, stateKey string, outContent interface{}) (err error) {
|
||||
u := cli.BuildURL("rooms", roomID, "state", string(eventType), stateKey)
|
||||
_, err = cli.MakeRequest("GET", u, nil, outContent)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
150
events.go
150
events.go
|
|
@ -2,8 +2,7 @@ package gomatrix
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"html"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type EventType string
|
||||
|
|
@ -60,6 +59,8 @@ type Event struct {
|
|||
Content Content `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 Unsigned `json:"unsigned,omitempty"` // Unsigned content set by own homeserver.
|
||||
|
||||
InviteRoomState []StrippedState `json:"invite_room_state"`
|
||||
}
|
||||
|
||||
func (evt *Event) GetStateKey() string {
|
||||
|
|
@ -69,6 +70,12 @@ func (evt *Event) GetStateKey() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
type StrippedState struct {
|
||||
Content Content `json:"content"`
|
||||
Type EventType `json:"type"`
|
||||
StateKey string `json:"state_key"`
|
||||
}
|
||||
|
||||
type Unsigned struct {
|
||||
PrevContent map[string]interface{} `json:"prev_content,omitempty"`
|
||||
PrevSender string `json:"prev_sender,omitempty"`
|
||||
|
|
@ -88,9 +95,15 @@ type Content struct {
|
|||
Info *FileInfo `json:"info,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// Membership key for easy access in m.room.member events
|
||||
Membership string `json:"membership,omitempty"`
|
||||
|
||||
RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
|
||||
|
||||
*PowerLevels
|
||||
*Member
|
||||
*Aliases
|
||||
*CanonicalAlias
|
||||
}
|
||||
|
||||
type serializableContent Content
|
||||
|
|
@ -103,11 +116,26 @@ func (content *Content) UnmarshalJSON(data []byte) error {
|
|||
return json.Unmarshal(data, (*serializableContent)(content))
|
||||
}
|
||||
|
||||
func (content *Content) UnmarshalPowerLevels() (pl PowerLevels, err error) {
|
||||
/*func (content *Content) UnmarshalPowerLevels() (pl PowerLevels, err error) {
|
||||
err = json.Unmarshal(content.VeryRaw, &pl)
|
||||
return
|
||||
}
|
||||
|
||||
func (content *Content) UnmarshalMember() (m Member, err error) {
|
||||
err = json.Unmarshal(content.VeryRaw, &m)
|
||||
return
|
||||
}
|
||||
|
||||
func (content *Content) UnmarshalAliases() (a Aliases, err error) {
|
||||
err = json.Unmarshal(content.VeryRaw, &a)
|
||||
return
|
||||
}
|
||||
|
||||
func (content *Content) UnmarshalCanonicalAlias() (ca CanonicalAlias, err error) {
|
||||
err = json.Unmarshal(content.VeryRaw, &ca)
|
||||
return
|
||||
}*/
|
||||
|
||||
func (content *Content) GetInfo() *FileInfo {
|
||||
if content.Info == nil {
|
||||
content.Info = &FileInfo{}
|
||||
|
|
@ -115,12 +143,38 @@ func (content *Content) GetInfo() *FileInfo {
|
|||
return content.Info
|
||||
}
|
||||
|
||||
type Member struct {
|
||||
Membership string `json:"membership,omitempty"`
|
||||
AvatarURL string `json:"avatar_url,omitempty"`
|
||||
Displayname string `json:"displayname,omitempty"`
|
||||
ThirdPartyInvite *ThirdPartyInvite `json:"third_party_invite,omitempty"`
|
||||
}
|
||||
|
||||
type ThirdPartyInvite struct {
|
||||
DisplayName string `json:"display_name"`
|
||||
Signed struct {
|
||||
Token string `json:"token"`
|
||||
Signatures json.RawMessage `json:"signatures"`
|
||||
MXID string `json:"mxid"`
|
||||
}
|
||||
}
|
||||
|
||||
type Aliases struct {
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
}
|
||||
|
||||
type CanonicalAlias struct {
|
||||
Alias string `json:"alias,omitempty"`
|
||||
}
|
||||
|
||||
type PowerLevels struct {
|
||||
Users map[string]int `json:"users"`
|
||||
usersLock sync.RWMutex `json:"-"`
|
||||
Users map[string]int `json:"users,omitempty"`
|
||||
UsersDefault int `json:"users_default,omitempty"`
|
||||
|
||||
Events map[string]int `json:"events"`
|
||||
EventsDefault int `json:"events_default,omitempty"`
|
||||
eventsLock sync.RWMutex `json:"-"`
|
||||
Events map[EventType]int `json:"events,omitempty"`
|
||||
EventsDefault int `json:"events_default,omitempty"`
|
||||
|
||||
StateDefaultPtr *int `json:"state_default,omitempty"`
|
||||
|
||||
|
|
@ -130,41 +184,102 @@ type PowerLevels struct {
|
|||
RedactPtr *int `json:"redact,omitempty"`
|
||||
}
|
||||
|
||||
func (pl PowerLevels) Invite() int {
|
||||
func (pl *PowerLevels) Invite() int {
|
||||
if pl.InvitePtr != nil {
|
||||
return *pl.InvitePtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl PowerLevels) Kick() int {
|
||||
func (pl *PowerLevels) Kick() int {
|
||||
if pl.KickPtr != nil {
|
||||
return *pl.KickPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl PowerLevels) Ban() int {
|
||||
func (pl *PowerLevels) Ban() int {
|
||||
if pl.BanPtr != nil {
|
||||
return *pl.BanPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl PowerLevels) Redact() int {
|
||||
func (pl *PowerLevels) Redact() int {
|
||||
if pl.RedactPtr != nil {
|
||||
return *pl.RedactPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl PowerLevels) StateDefault() int {
|
||||
func (pl *PowerLevels) StateDefault() int {
|
||||
if pl.StateDefaultPtr != nil {
|
||||
return *pl.StateDefaultPtr
|
||||
}
|
||||
return 50
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) GetUserLevel(userID string) int {
|
||||
pl.usersLock.RLock()
|
||||
level, ok := pl.Users[userID]
|
||||
pl.usersLock.RUnlock()
|
||||
if !ok {
|
||||
return pl.UsersDefault
|
||||
}
|
||||
return level
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) SetUserLevel(userID string, level int) {
|
||||
pl.usersLock.Lock()
|
||||
if level == pl.UsersDefault {
|
||||
delete(pl.Users, userID)
|
||||
} else {
|
||||
pl.Users[userID] = level
|
||||
}
|
||||
pl.usersLock.Unlock()
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) EnsureUserLevel(userID string, level int) bool {
|
||||
existingLevel := pl.GetUserLevel(userID)
|
||||
if existingLevel != level {
|
||||
pl.SetUserLevel(userID, level)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) GetEventLevel(eventType EventType, isState bool) int {
|
||||
pl.eventsLock.RLock()
|
||||
level, ok := pl.Events[eventType]
|
||||
pl.eventsLock.RUnlock()
|
||||
if !ok {
|
||||
if isState {
|
||||
return pl.StateDefault()
|
||||
}
|
||||
return pl.EventsDefault
|
||||
}
|
||||
return level
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) SetEventLevel(eventType EventType, isState bool, level int) {
|
||||
pl.eventsLock.Lock()
|
||||
if (isState && level == pl.StateDefault()) || (!isState && level == pl.EventsDefault) {
|
||||
delete(pl.Events, eventType)
|
||||
} else {
|
||||
pl.Events[eventType] = level
|
||||
}
|
||||
pl.eventsLock.Unlock()
|
||||
}
|
||||
|
||||
func (pl *PowerLevels) EnsureEventLevel(eventType EventType, isState bool, level int) bool {
|
||||
existingLevel := pl.GetEventLevel(eventType, isState)
|
||||
if existingLevel != level {
|
||||
pl.SetEventLevel(eventType, isState, level)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type FileInfo struct {
|
||||
MimeType string `json:"mimetype,omitempty"`
|
||||
ThumbnailInfo *FileInfo `json:"thumbnail_info,omitempty"`
|
||||
|
|
@ -191,16 +306,3 @@ type InReplyTo struct {
|
|||
// Not required, just for future-proofing
|
||||
RoomID string `json:"room_id,omitempty"`
|
||||
}
|
||||
|
||||
var htmlRegex = regexp.MustCompile("<[^<]+?>")
|
||||
|
||||
// GetHTMLMessage returns an HTMLMessage with the body set to a stripped version of the provided HTML, in addition
|
||||
// to the provided HTML.
|
||||
func GetHTMLMessage(msgtype MessageType, htmlText string) Content {
|
||||
return Content{
|
||||
Body: html.UnescapeString(htmlRegex.ReplaceAllLiteralString(htmlText, "")),
|
||||
MsgType: msgtype,
|
||||
Format: "org.matrix.custom.html",
|
||||
FormattedBody: htmlText,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ type ReqCreateRoom struct {
|
|||
Invite []string `json:"invite,omitempty"`
|
||||
Invite3PID []ReqInvite3PID `json:"invite_3pid,omitempty"`
|
||||
CreationContent map[string]interface{} `json:"creation_content,omitempty"`
|
||||
InitialState []Event `json:"initial_state,omitempty"`
|
||||
InitialState []*Event `json:"initial_state,omitempty"`
|
||||
Preset string `json:"preset,omitempty"`
|
||||
IsDirect bool `json:"is_direct,omitempty"`
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue