Documentation ¶
Overview ¶
Package matrix implements a matrix client. This includes a lot of abstractionns on top of the http api. This package tries to use as few as possible HTTP requests. We try to accomplish this by saving as much information as possible from the /sync API endpoint. This means that whenever we initialize a new backend, we do a request with full_state=true which might take some seconds to complete. To avoid this you should use a persistent backend. This package is fully thread-safe. All errors returned by methods in this package are (unless otherwise noted) either a NetworkError or a LogicError wrapping the original error
Index ¶
- Constants
- Variables
- func ResolveHomeserverURL(cli *http.Client, serverName string) (*url.URL, error)
- func SplitMxID(id string) (localpart string, serverName string, err error)
- type AccountDataEvent
- type ApplicationService
- type ApplicationServiceOpts
- type Backend
- type BaseEvent
- type Client
- func (cli *Client) AccessToken() string
- func (cli *Client) Device() (Device, bool)
- func (cli *Client) DeviceID() string
- func (cli *Client) DownloadFile(url *url.URL, filename string) (File, error)
- func (cli *Client) DownloadThumbnail(url *url.URL, width, height int, method ThumbnailMethod) (Thumbnail, error)
- func (cli *Client) LoadToken(mxid, deviceID string) error
- func (cli *Client) Login(mxid string, password string) error
- func (cli *Client) Logout() error
- func (cli *Client) LogoutAll() error
- func (cli *Client) MxID() string
- func (cli *Client) Notify(c chan<- Event)
- func (cli *Client) SendToDevice(encrypted bool, eventType string, ...) error
- func (cli *Client) SetupCryptoSession() error
- func (cli *Client) Stop(c chan<- Event)
- func (cli *Client) Sync(ctx context.Context, opts *SyncOpts) error
- func (cli *Client) UploadFile(file File) (*url.URL, error)
- func (cli *Client) User() (User, bool)
- type ClientOpts
- type CreateRoomOpts
- type CreateRoomPreset
- type CryptoBackend
- type CryptoError
- type Device
- type DeviceInfo
- type EphemeralEvent
- type Event
- type File
- type History
- type JSONEvent
- type Logger
- type LogicError
- type Member
- type MembershipState
- type MissingContentKeyError
- type NetworkError
- type Notifier
- type Registration
- type RegistrationNamespace
- type RegistrationNamespaces
- type Room
- func (r Room) AccountData(type_ string) (AccountDataEvent, bool)
- func (r Room) Displayname() string
- func (r Room) Forget() error
- func (r Room) GetState(eventType, stateKey string) (StateEvent, bool)
- func (r Room) History() History
- func (r Room) Invite(u User) error
- func (r Room) Leave() error
- func (r Room) Member(mxid string) *Member
- func (r Room) Members() []Member
- func (r Room) Notify(c chan<- Event)
- func (r Room) SendRoomEvent(eventType string, content map[string]interface{}) (string, error)
- func (r Room) SendStateEvent(eventType string, stateKey string, content map[string]interface{}) (string, error)
- func (r Room) State() MembershipState
- func (r Room) Stop(c chan<- Event)
- type RoomEvent
- func (e RoomEvent) Base() BaseEvent
- func (e RoomEvent) Decrypt() (RoomEvent, error)
- func (e RoomEvent) MarshalJSON() ([]byte, error)
- func (e RoomEvent) Own() bool
- func (e *RoomEvent) UnmarshalJSON(data []byte) error
- func (e RoomEvent) WithClient(cli *Client) RoomEvent
- func (e RoomEvent) WithRoom(room Room) RoomEvent
- type RoomEventUnsigned
- type RoomVisibility
- type StateEvent
- type SyncOpts
- type Thumbnail
- type ThumbnailMethod
- type ToDeviceEvent
- type User
Examples ¶
Constants ¶
const ( MegolmName = "m.megolm.v1.aes-sha2" OlmName = "m.olm.v1.curve25519-aes-sha2" )
const ( PrivateChat CreateRoomPreset = "private_chat" PublicChat = "public_chat" TrustedPrivateChat = "trusted_private_chat" )
const CryptoSupport = true
If set to true the library is able to handle encrypted events
Variables ¶
var ( ErrDeviceKeys = errors.New("the device is lacking a ed25519 or curve25519 key") ErrCryptoDisabled = errors.New("cryptography has been disabled in this build") ErrMalformedEvent = errors.New("event does not have all neccessary keys") ErrUnknownSession = errors.New("olm/megolm session not known") ErrUnsupportedAlgorithm = errors.New("the algorithm used to encrypt the event is not supported") ErrSessionNotSetUp = errors.New("no cryptography session has been set up for this device") ErrAlreadySetUp = errors.New("the session for this device has already been set up") )
CryptoError
var ErrInvalidURL = errors.New("invalid mxc:// url")
var ErrUnsupportedVersion = errors.New("the homeserver does not support API version r0.5.0. The Client might or might not work correctly")
Functions ¶
func ResolveHomeserverURL ¶
ResolveHomeserverURL gets the actual URL of a homeserver based on the server name from a mxid. It returns a NetworkError if the http transport was not successful and a LogicError if the server provided a broken response (e.g malformatted JSON) TODO Identity server & extra information XXX Really use LogicError here?
Types ¶
type AccountDataEvent ¶
type AccountDataEvent struct { Type string `json:"type"` Content map[string]interface{} `json:"content"` // contains filtered or unexported fields }
AccountDataEvent is a matrix account data event. If this event is attached to a Room, this Room can be obtained using the Room method.
func (AccountDataEvent) Base ¶
func (e AccountDataEvent) Base() BaseEvent
Base implements the Event interface
func (AccountDataEvent) Room ¶
func (e AccountDataEvent) Room() *Room
Room returns the room on which the event was stored.
func (AccountDataEvent) WithRoom ¶
func (e AccountDataEvent) WithRoom(room Room) AccountDataEvent
WithRoom sets the originating room of the RoomEvent. This has to be called after loading the struct from any kind of storage format (e.g JSON). Otherwise calling methods of e.Room will panic at some point
type ApplicationService ¶
type ApplicationService struct {
// contains filtered or unexported fields
}
ApplicationService allows to utilize the application service API.
func NewApplicationService ¶
func NewApplicationService(reg Registration, opts ApplicationServiceOpts) *ApplicationService
func (*ApplicationService) Notify ¶
func (as *ApplicationService) Notify(ch chan<- Event)
Notify implements the Notifier interface. The channel will receive all events the application service is interested in.
func (*ApplicationService) Stop ¶
func (as *ApplicationService) Stop(ch chan<- Event)
type ApplicationServiceOpts ¶
type ApplicationServiceOpts struct {
Addr string
}
type Backend ¶
type Backend interface { // Initialize configures the backend to store information // for the provided device. This should be called only // when a new device is created or mxid, deviceID and // access token have been persisted in another way. // Initialize panics if there is a persisted session // available (i.e if Open(mxid, deviceID) would return // nil. // Calling Initialize multiple times panics. Initialize(mxid, deviceID, accessToken string) // Open configures the backend to load already an already // persisted session. This should be called if the // Backend implementation is able to persist information // between restarts. If the provided mxid-deviceID // combination is not known this returns an error. // Calling Open multiple times panics. Open(mxid, deviceID string) error // MxID returns the MxID of the user owing the device. // This method must return an empty string when the backend // has not been configured yet. MxID() string // DeviceID returns the device ID of the device. // This method must return an empty string when the backend // has not been configured yet. DeviceID() string // AccessToken returns the access token used by the device. // This method must return an empty string when the backend // has not been configured yet. AccessToken() string // AccountData gets a account data event of the specified // type from the given room. If room is nil the event // is searched in the users global account data. // If no event is found nil is returned. AccountData(room *Room, type_ string) (AccountDataEvent, bool) // UpdateAccountData updates the chached account data. UpdateAccountData(AccountDataEvent) // RoomState gets a StateEvent from a room. RoomState(room Room, type_, key string) (StateEvent, bool) // RoomStateList gets all state events of the specified type // from the room. RoomStateList(room Room, type_ string) []StateEvent // UpdateRoomState updates the cached room state. UpdateRoomState(event StateEvent) // AddLatestEvents adds events freshly received from the /sync // endpoint and the prevBatch token used to iterate room history // into the cache. AddLatestEvents(room Room, events []Event, prevBatch string) // LatestEvents returns the latest Events received from the /sync // endpoint and the prevBatch token from the cache. The order of the // events must stay the same. LatestEvents(room Room) ([]Event, string) // DeviceInfo returns the device info for a specific device DeviceInfo(user User, id string) (DeviceInfo, bool) // DeviceList returns all devices of the user. Note that this only contains devices that have identity keys // set up (as there is no possibility to see devices of a user that do not support encryption). DeviceList(user User) []Device // DeviceListUntrack removes all stored devices for the given user. This is called when the user's ID appears // in the "left" secion of the device_lists property of the /sync response. DeviceListUntrack(user User) // DeviceListUpdate updates the device list of a user. "devices" contains all current devices of the user. The Backend // must completely replace the list it has currently stored. DeviceListUpdate(user User, devices []DeviceInfo) CryptoBackend }
The Backend is responsible for storing session information (mxid, device ID, access token) and caching. A Backend is tied to exactly one session (or device in matrix terminology). A Backend implementation must be threadsafe! A Backend implementation should not try to set correct internal values on the returned structs (with WithClient or WithRoom) the client will handle this. If neither Initialize nor Open have been called on a backend, all methods except for MxID, DeviceID and AccessToken may panic or return otherwise unexpected results.
type Client ¶
type Client struct { // A event is sent to this channel when the first sync request has completed. // If the Sync routine is stopped and then restarted a event is again sent. InitialSyncDone chan struct{} // contains filtered or unexported fields }
Client implements communication using the matrix protocol. All methods interacting with the content repository do not implement any kind of caching since there is no one-fits-all solution to this. To use caching you either have to build your own solution or use whats in git.sr.ht/~f4814n/matrix/util/cache
Example (Echo) ¶
package main import ( "context" "fmt" "os" "git.sr.ht/~f4814n/matrix" "git.sr.ht/~f4814n/matrix/backend/memory" ) func main() { mxid := os.Getenv("MATRIX_TEST_MXID") password := os.Getenv("MATRIX_TEST_PASSWORD") cli := matrix.NewClient(matrix.ClientOpts{Backend: memory.New()}) if err := cli.Login(mxid, password); err != nil { fmt.Println(err.Error()) return } go cli.Sync(context.Background(), &matrix.SyncOpts{ OnError: func(err error) error { fmt.Printf("Sync Error: %s\n", err) return nil // Continue syncing }, }) <-cli.InitialSyncDone // Avoid echoing events sent before the client was started events := make(chan matrix.Event) cli.Notify(events) for event := range events { if event, ok := event.(matrix.RoomEvent); ok { if event.Type == "m.room.message" && !event.Own() { _, err := event.Room.SendRoomEvent("m.room.message", event.Content) if err != nil { fmt.Printf("Could not send event: %s", err) } } } } }
Output:
func NewClient ¶
func NewClient(opts ClientOpts) *Client
NewClient creates a new client. This only initializes everything needed but does not make any attempt to use the network.
func (*Client) AccessToken ¶
AccessToken returns the access token used by the client. "" if there is no token
func (*Client) Device ¶
Device returns the device the client is authenticated as. False if the client is not authenticated
func (*Client) DownloadFile ¶
DownloadFile downloads a file from the content repository of the homeserver. url must be a valid mxc:// URL.
func (*Client) DownloadThumbnail ¶
func (cli *Client) DownloadThumbnail(url *url.URL, width, height int, method ThumbnailMethod) (Thumbnail, error)
DownloadThumbnail downloads a thumbnail of the specified URL from the homeserver
func (*Client) LoadToken ¶
LoadToken calls the Open method of the backend with the provided parameters, checks if the homeserver exists, configures the client to use the homeserver and finally calls the whoami API endpoint to check, whether the access token matches the mxID.
func (*Client) Login ¶
Login using a matrix user id and a password (m.login.password)
Example ¶
package main import ( "fmt" "os" "git.sr.ht/~f4814n/matrix" "git.sr.ht/~f4814n/matrix/backend/memory" ) func main() { mxid := os.Getenv("MATRIX_TEST_MXID") password := os.Getenv("MATRIX_TEST_PASSWORD") cli := matrix.NewClient(matrix.ClientOpts{Backend: memory.New()}) if err := cli.Login(mxid, password); err != nil { fmt.Println(err.Error()) return } fmt.Println("Login successful") }
Output:
func (*Client) Notify ¶
Notify implements the Notify interface. This will contain all events received.
Example ¶
package main import ( "context" "fmt" "os" "git.sr.ht/~f4814n/matrix" "git.sr.ht/~f4814n/matrix/backend/memory" ) func main() { mxid := os.Getenv("MATRIX_TEST_MXID") password := os.Getenv("MATRIX_TEST_PASSWORD") cli := matrix.NewClient(matrix.ClientOpts{Backend: memory.New()}) if err := cli.Login(mxid, password); err != nil { fmt.Println(err.Error()) return } events := make(chan matrix.Event, 100) cli.Notify(events) go func() { for event := range events { fmt.Printf("%#v\n", event) } }() if err := cli.Sync(context.Background(), nil); err != nil { fmt.Println(err.Error()) } }
Output:
func (*Client) SendToDevice ¶
func (cli *Client) SendToDevice(encrypted bool, eventType string, messages map[string]map[string]map[string]interface{}) error
SendToDevice sends a to-device event. If encrypted is true, the event will be encrypted using OLM and sent as an m.room.encrypted event. messages is a map from user ID to device ID to event content.
func (*Client) SetupCryptoSession ¶
SetupCryptoSession will set up a crypto session for this device. This only has to be called once for a session (preferrably directly after calling cli.Login). Will return CryptoError{Err: ErrCryptoDisabled} if the build does not support cryptography. Will return CryptoError{Err: ErrAlreadySetUp} All methods encrypting/decrypting events will return CryptoError{Err: ErrSessionNotSetUp} if this has not been called before attempting to encrypt/decrypt.
func (*Client) Sync ¶
Sync starts receiving change events. This will start long-polling /sync and supply all Changers with new events. This can be stopped and then restarted without having to discard Changers. Stop this by terminating ctx. The returned error is either a NetworkError, a LogicError or Context.Canceled / Context.DeadlineExceeded.
func (*Client) UploadFile ¶
UploadFile uploads a file to the content repository of the homeserver and returns the created mxc:// URL.
type ClientOpts ¶
type ClientOpts struct { // HTTP Client to use. If nil http.DefaultClient will be used HTTPClient *http.Client // Backend Backend Backend // Logger to use. When no logger is supplied a no-op logger is used. Logger Logger }
ClientOpts are optional options passed to Client. NewClient is able to handle ClientOpts values which have nil fields or even are nil.
type CreateRoomOpts ¶
type CreateRoomOpts struct { // If Visibility is Public the room will be added to the public room directory // of the server. Defaults to Private Visibility RoomVisibility // The desired room alias *local part*. If set, a room alias will be created // and mapped to the newly created room. The alias will belong to the same // homeserver which created the room. Alias string // If set, an m.room.name event will be sent into the room. Name string // If set, an m.room.topic event will be sent into the room. Topic string // A list of users to invite to the room. Invite []User // The room version to set for the room. If not set, the homeserver will use // its configured default. RoomVersion string // A list of state events to set in the new room. Each element of the slice // is marshaled to JSON. The resulting JSON must be an object containing the // "type", "state_key" and "content" keys. InitialState []interface{} // Convenience parameter for setting various default state events based on // a preset. Preset CreateRoomPreset // Will set the is_direct flag on the events sent to the invited users. // Defaults to false. IsDirect bool // The power level content to override in the default power level event. // This object is applied on top of the generated m.room.power_levels event // content prior to it being sent to the room. Defaults to overriding nothing. PowerLevelContentOverride map[string]interface{} }
type CreateRoomPreset ¶
type CreateRoomPreset string
CreateRoomPreset is a convenience enum used in room creation. For more information see https://matrix.org/docs/spec/client_server/r0.5.0#post-matrix-client-r0-createroom
type CryptoBackend ¶
type CryptoBackend interface { Account() string UpdateAccount(string) Sessions(deviceKey string) []string UpdateSessions(deviceKey string, sessions []string) InboundGroupSession(roomID, deviceKey, sessionID string) string AddInboundGroupSession(roomID, deviceKey, sessionID, session string) OutboundGroupSessions(roomID string) []string UpdateOutboundGroupSessions(roomID string, sessions []string) }
type CryptoError ¶
type CryptoError struct {
Err error
}
A CryptoError is returned, if something went wrong during encrypting or decrypting an event.
func (CryptoError) Error ¶
func (e CryptoError) Error() string
func (CryptoError) Unwrap ¶
func (e CryptoError) Unwrap() error
type Device ¶
type Device struct { ID string // contains filtered or unexported fields }
func (Device) Info ¶
func (d Device) Info() DeviceInfo
type DeviceInfo ¶
type DeviceInfo struct { ID string Algorithms []string Keys map[string]string Signatures map[string]map[string]string }
func (DeviceInfo) Curve25519 ¶
func (d DeviceInfo) Curve25519() (string, bool)
Curve25519 returns the public part of the devices Curve25519 identity key
func (DeviceInfo) Ed25519 ¶
func (d DeviceInfo) Ed25519() (string, bool)
Ed25519 returns the public part of the devices Ed25519 fingerprint key
func (DeviceInfo) Supports ¶
func (d DeviceInfo) Supports(algorithm string) bool
Supports returns bool if the device supports the supplied algorithm. The library must support the algorithm too
type EphemeralEvent ¶
type EphemeralEvent struct { Type string Content map[string]interface{} // contains filtered or unexported fields }
EphemeralEvent is a ephemeral matrix event.
func (EphemeralEvent) Base ¶
func (e EphemeralEvent) Base() BaseEvent
Base implements the Event interface
func (EphemeralEvent) Room ¶
func (e EphemeralEvent) Room() Room
func (EphemeralEvent) WithRoom ¶
func (e EphemeralEvent) WithRoom(room Room) EphemeralEvent
type Event ¶
type Event interface {
Base() BaseEvent
}
Event is the interface implemented by the types to represent all kinds of matrix events.
type File ¶
type File struct { Name string Type string Size int64 Content io.ReadCloser }
File represents content of the matrix content repository. Don't forget to Close() File.Content after using it.
type History ¶
type History struct { // Contains the current events. Paginated using History.Next() Events []Event Err error // contains filtered or unexported fields }
History makes the room history accessible.
Example ¶
package main import ( "context" "fmt" "os" "git.sr.ht/~f4814n/matrix" "git.sr.ht/~f4814n/matrix/backend/memory" ) func main() { mxid := os.Getenv("MATRIX_TEST_MXID") password := os.Getenv("MATRIX_TEST_PASSWORD") roomID := os.Getenv("MATRIX_TEST_ROOM") cli := matrix.NewClient(matrix.ClientOpts{Backend: memory.New()}) if err := cli.Login(mxid, password); err != nil { fmt.Println(err.Error()) return } go cli.Sync(context.Background(), &matrix.SyncOpts{ OnError: func(err error) error { fmt.Printf("Sync Error: %s\n", err) return nil // Continue syncing }, }) // The initial sync must be completed so we know the prev_token of the sync request <-cli.InitialSyncDone room, err := matrix.LoadRoom(cli, roomID) if err != nil { panic(err) } history := room.History() for history.Next() { if history.Err != nil { panic(err) } for _, event := range history.Events { fmt.Printf("%#v\n", event) } } }
Output:
func (*History) Next ¶
Next uses the room messages API to traverse the history in a backwards way. If there is a communication error, next sets History.Err to the error and returns true. Even though the messages API does not return the most recent event (if it was sent by the last sync response), History includes those events too.
type JSONEvent ¶
type JSONEvent struct {
Event Event
}
JSONEvent uses a custom UnmarshalJSON mehtod to detect wheter the decoded event is a StateEvent or a RoomEvent
Example (Room) ¶
raw := []byte(` { "content": { "body": "This is an example text message", "msgtype": "m.text", "format": "org.matrix.custom.html", "formatted_body": "<b>This is an example text message</b>" }, "type": "m.room.message", "event_id": "$143273582443PhrSn:example.org", "room_id": "!726s6s6q:example.com", "sender": "@example:example.org", "origin_server_ts": 1432735824653, "unsigned": { "age": 1234 } } `) var helper JSONEvent err := json.Unmarshal(raw, &helper) if err != nil { panic(err) } fmt.Printf("%T\n", helper.Event) fmt.Printf("%+v\n", helper.Event)
Output: matrix.RoomEvent {Content:map[body:This is an example text message format:org.matrix.custom.html formatted_body:<b>This is an example text message</b> msgtype:m.text] Type:m.room.message ID:$143273582443PhrSn:example.org OriginServerTS:2015-05-27 16:10:24.653 +0200 CEST Unsigned:{Age:1234 RedactedBecause:<nil> TransactionID:} Sender:{User:{ID:@example:example.org cli:<nil>} Room:{ID: cli:<nil>}} Room:{ID: cli:<nil>}}
Example (State) ¶
raw := []byte(` { "content": { "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", "displayname": "Alice Margatroid", "membership": "join" }, "type": "m.room.member", "event_id": "$143273582443PhrSn:example.org", "unsigned": { "age": 1234, "transaction_id": "" }, "state_key": "@alice:example.org", "origin_server_ts": 1603152000000, "sender": "@example:example.org" } `) var helper JSONEvent err := json.Unmarshal(raw, &helper) if err != nil { panic(err) } fmt.Printf("%T\n", helper.Event) fmt.Printf("%+v\n", helper.Event)
Output: matrix.StateEvent {Content:map[avatar_url:mxc://example.org/SEsfnsuifSDFSSEF displayname:Alice Margatroid membership:join] Type:m.room.member ID:$143273582443PhrSn:example.org OriginServerTS:2020-10-20 02:00:00 +0200 CEST Unsigned:{Age:1234 RedactedBecause:<nil> TransactionID:} StateKey:@alice:example.org PrevContent:map[] Sender:{User:{ID:@example:example.org cli:<nil>} Room:{ID: cli:<nil>}} Room:{ID: cli:<nil>}}
func (*JSONEvent) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface
type LogicError ¶
type LogicError struct {
Err error
}
A LogicError is returned, if the HTTP connection was successful but the operation failed anyway. (For example due to insufficient authorization)
func (LogicError) Error ¶
func (e LogicError) Error() string
func (LogicError) Unwrap ¶
func (e LogicError) Unwrap() error
type Member ¶
Member is a User with the additional information from a single room.
func (Member) Displayname ¶
Displayname gets the displayname of the user by searching m.room.member state events. If no name is set it returns the users MxID.
func (Member) Notify ¶
Notify implements the Notifier interface. This can not be used to be notified about ephemeral events relevant for the user (e.g. m.typing events), since it is not possible to attribute all ephemeral events to a certain set of users.
func (Member) State ¶
func (m Member) State() MembershipState
type MembershipState ¶
type MembershipState uint8
const ( Invite MembershipState = iota Join Leave Ban Knock Unspecified )
func (MembershipState) String ¶
func (i MembershipState) String() string
type MissingContentKeyError ¶
type MissingContentKeyError struct {
Key string
}
func (MissingContentKeyError) Error ¶
func (e MissingContentKeyError) Error() string
type NetworkError ¶
type NetworkError struct {
Err error
}
A NetworkError is returned, if a correct HTTP transmission was not possible for whatever reason
func (NetworkError) Error ¶
func (e NetworkError) Error() string
func (NetworkError) Unwrap ¶
func (e NetworkError) Unwrap() error
type Notifier ¶
type Notifier interface { // A copy of each event relecant to the Updater is sent here. It is up to the // use to ensure that the channel is empty. The event will be discarded, if // the channel is not empty. Calling this method with the same argument // twice will panic. Notify(chan<- Event) // Stop sending to the specified channel. This panics if the channel was // not registered before using Updater.Update() or if called multiple // times. Stop(chan<- Event) }
A Notifier (Client, User, Member, Room) can receive updated events from a running Client.
type Registration ¶
type Registration struct { ID string `yaml:"id"` URL string `yaml:"url"` ASToken string `yaml:"as_token"` HSToken string `yaml:"hs_token"` SenderLocalpart string `yaml:"sender_localpart"` Namespaces RegistrationNamespaces `yaml:"namespaces"` RateLimited bool `yaml:"rate_limited"` Protocols []string `yaml:"protocols"` }
Registration is used to authenticate a ApplicationService to the homeserver. https://matrix.org/docs/spec/application_service/r0.1.2#registration
type RegistrationNamespace ¶
type RegistrationNamespaces ¶
type RegistrationNamespaces struct { Users []RegistrationNamespace `yaml:"users"` Aliases []RegistrationNamespace `yaml:"aliases"` Rooms []RegistrationNamespace `yaml:"rooms"` }
type Room ¶
type Room struct { // The matrix ID of the room ID string // contains filtered or unexported fields }
Room represents a matrix room. A room value is always tied to a client, that is used to do the actual communication. Multiple room values describing the same room may be used simultaneously. Room is thread-safe.
Example ¶
package main import ( "context" "fmt" "os" "git.sr.ht/~f4814n/matrix" "git.sr.ht/~f4814n/matrix/backend/memory" ) func main() { mxid := os.Getenv("MATRIX_TEST_MXID") password := os.Getenv("MATRIX_TEST_PASSWORD") roomID := os.Getenv("MATRIX_TEST_ROOM") cli := matrix.NewClient(matrix.ClientOpts{Backend: memory.New()}) if err := cli.Login(mxid, password); err != nil { fmt.Println(err.Error()) return } go cli.Sync(context.Background(), &matrix.SyncOpts{ OnError: func(err error) error { fmt.Printf("Sync Error: %s\n", err) return nil // Continue syncing }, }) <-cli.InitialSyncDone room, err := matrix.LoadRoom(cli, roomID) if err != nil { panic(err) } if state := room.State(); state != matrix.Join { fmt.Printf("Your state is %s. This might not work as expected\n", state) } events := make(chan matrix.Event, 100) room.Notify(events) for event := range events { fmt.Println(event) } }
Output:
func CreateRoom ¶
func CreateRoom(cli *Client, opts CreateRoomOpts) (Room, error)
CreateRoom creates a new room.
func LoadRoom ¶
LoadRoom takes a id or alias as argument and calls LoadRoomID or LoadRoomAlias depending on the first sign of the id.
func LoadRoomAlias ¶
LoadRoomAlias loads a existent room identified by the room alias.
func LoadRoomID ¶
LoadRoomID loads a existent room identified by the room ID. This call is very fast (no HTTP Request) for rooms the user is invited to, has joined or has already left (for all rooms that are somehow part of the /sync endpoint). For other rooms this tries to look up the ID.
func (Room) AccountData ¶
func (r Room) AccountData(type_ string) (AccountDataEvent, bool)
AccountData returns an AccountDataEvent of the given type if it exists
func (Room) Displayname ¶
Displayname returns the rooms display name. The name is calculated according to https://matrix.org/docs/spec/client_server/r0.5.0#calculating-the-display-name-for-a-room
func (Room) Forget ¶
Forget forgets the room. The history of the room will no longer be accessible. If the user is currently joined to the room, they must leave the room before calling this.
func (Room) GetState ¶
func (r Room) GetState(eventType, stateKey string) (StateEvent, bool)
GetState gets a specific event from the room state. If no such state event is known the return value is nil.
func (Room) History ¶
History makes the history beginning from the most recently received prev_batch (/sync endpoint) accessible.
func (Room) Member ¶
Member returns the Member with the given mxid in this room. If the specified user has no m.room.member event in this room it will return nil
func (Room) Members ¶
Members returns all Members of this room. At the moment lazy loading of room members is not used. So this method can not return an error.
func (Room) SendRoomEvent ¶
SendRoomEvent sends a room event to the room and returns the event ID and possibly an error.
func (Room) SendStateEvent ¶
func (r Room) SendStateEvent(eventType string, stateKey string, content map[string]interface{}) (string, error)
SendStateEvent sends a state event to the room and returns the event ID and possibly an error.
func (Room) State ¶
func (r Room) State() MembershipState
State returns the MembershipState of the Client in this room.
type RoomEvent ¶
type RoomEvent struct { Content map[string]interface{} `json:"content"` Type string `json:"type"` ID string `json:"event_id"` OriginServerTS time.Time `json:"origin_server_ts"` Unsigned RoomEventUnsigned `json:"unsigned"` Sender Member `json:"sender"` Room Room `json:"-"` }
RoomEvent is a matrix room event that is not a state event at the same time. RoomEvent implements the interfaces of encoding/json in a way which allows to marshal and unmarshal JSON in the format the matrix spec dictates. Certain information about the used client and associated room will be lost in this process and has to be restored using the WithClient and WithRoom methods after Decoding from JSON
func (RoomEvent) MarshalJSON ¶
MarshalJSON implements the json.Marshaler interface
Example ¶
t, _ := time.Parse("2006-Jan-02", "2020-Oct-20") e := RoomEvent{ Content: map[string]interface{}{ "msgtype": "m.text", "body": "Hello there", }, Type: "m.room.message", ID: "$143273582443PhrSn:example.org", OriginServerTS: t, Unsigned: RoomEventUnsigned{ Age: 1234, }, // Information about the used client and the originating room is lost during marshal // RoomEvent.WithClient and RoomEvent.WithRoom can be used to change this information Sender: Member{User: User{ID: "@example:example.org"}, Room: Room{ID: "!726s6s6q:example.com"}}, } out, err := json.Marshal(e) if err != nil { panic(err) } var indent bytes.Buffer json.Indent(&indent, out, "", "\t") indent.WriteTo(os.Stdout)
Output: { "content": { "body": "Hello there", "msgtype": "m.text" }, "type": "m.room.message", "event_id": "$143273582443PhrSn:example.org", "unsigned": { "age": 1234, "transaction_id": "" }, "origin_server_ts": 1603152000000, "sender": "@example:example.org" }
func (RoomEvent) Own ¶
Own is true if the event was sent by the same user the client is currently authenticated as.
func (*RoomEvent) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface
Example ¶
raw := []byte(` { "content": { "body": "This is an example text message", "msgtype": "m.text", "format": "org.matrix.custom.html", "formatted_body": "<b>This is an example text message</b>" }, "type": "m.room.message", "event_id": "$143273582443PhrSn:example.org", "room_id": "!726s6s6q:example.com", "sender": "@example:example.org", "origin_server_ts": 1432735824653, "unsigned": { "age": 1234 } } `) var e RoomEvent err := json.Unmarshal(raw, &e) if err != nil { panic(err) } fmt.Printf("%+v\n", e)
Output: {Content:map[body:This is an example text message format:org.matrix.custom.html formatted_body:<b>This is an example text message</b> msgtype:m.text] Type:m.room.message ID:$143273582443PhrSn:example.org OriginServerTS:2015-05-27 16:10:24.653 +0200 CEST Unsigned:{Age:1234 RedactedBecause:<nil> TransactionID:} Sender:{User:{ID:@example:example.org cli:<nil>} Room:{ID: cli:<nil>}} Room:{ID: cli:<nil>}}
func (RoomEvent) WithClient ¶
WithClient sets the underlying client of the RoomEvent. This has to be called after loading the struct from any kind of storage format (e.g JSON). Otherwise calling methods of e.Sender and e.Room will panic at some point
type RoomEventUnsigned ¶
type RoomEventUnsigned struct { Age int64 `json:"age,omitempty"` RedactedBecause Event `json:"redacted_because,omitempty"` TransactionID string `json:"transaction_id,omitemtpy"` }
RoomEventUnsigned is used within RoomEvent.
type RoomVisibility ¶
type RoomVisibility string
RoomVisibility shows the visibility state of the room. NB: This should not be confused with join_rules which also uses the word public.
const ( // Public indicates that the room is part of the public room list. Public RoomVisibility = "public" // Private indicates that the room is not part of the public room list. Private = "private" )
type StateEvent ¶
type StateEvent struct { Content map[string]interface{} `json:"content"` Type string `json:"type"` ID string `json:"event_id"` OriginServerTS time.Time `json:"origin_server_ts"` Unsigned RoomEventUnsigned `json:"unsigned,omitempty"` StateKey string `json:"state_key"` PrevContent map[string]interface{} `json:"prev_content,omitempty"` Sender Member `json:"sender"` Room Room `json:"-"` }
StateEvent is a matrix state event.
func (StateEvent) MarshalJSON ¶
func (e StateEvent) MarshalJSON() ([]byte, error)
MarshalJSON implements the json.Marshaler interface
Example ¶
t, _ := time.Parse("2006-Jan-02", "2020-Oct-20") e := StateEvent{ Content: map[string]interface{}{ "membership": "join", "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", "displayname": "Alice Margatroid", }, Type: "m.room.member", ID: "$143273582443PhrSn:example.org", OriginServerTS: t, StateKey: "@alice:example.org", Unsigned: RoomEventUnsigned{ Age: 1234, }, // Information about the used client and the originating room is lost during marshal // RoomEvent.WithClient and RoomEvent.WithRoom can be used to change this information Sender: Member{User: User{ID: "@example:example.org"}, Room: Room{ID: "!726s6s6q:example.com"}}, } out, err := json.Marshal(e) if err != nil { panic(err) } var indent bytes.Buffer json.Indent(&indent, out, "", "\t") indent.WriteTo(os.Stdout)
Output: { "content": { "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", "displayname": "Alice Margatroid", "membership": "join" }, "type": "m.room.member", "event_id": "$143273582443PhrSn:example.org", "unsigned": { "age": 1234, "transaction_id": "" }, "state_key": "@alice:example.org", "origin_server_ts": 1603152000000, "sender": "@example:example.org" }
func (StateEvent) Own ¶
func (e StateEvent) Own() bool
Own is true if the event was sent by the same user the client is currently authenticated as.
func (*StateEvent) UnmarshalJSON ¶
func (e *StateEvent) UnmarshalJSON(data []byte) error
UnmarshalJSON impelments the json.Unmarshaler interface
Example ¶
raw := []byte(` { "content": { "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", "displayname": "Alice Margatroid" }, "type": "m.room.member", "event_id": "$143273582443PhrSn:example.org", "sender": "@example:example.org", "origin_server_ts": 1432735824653, "unsigned": { "age": 1234 } } `) var e RoomEvent err := json.Unmarshal(raw, &e) if err != nil { panic(err) } fmt.Printf("%+v\n", e)
Output: {Content:map[avatar_url:mxc://example.org/SEsfnsuifSDFSSEF displayname:Alice Margatroid] Type:m.room.member ID:$143273582443PhrSn:example.org OriginServerTS:2015-05-27 16:10:24.653 +0200 CEST Unsigned:{Age:1234 RedactedBecause:<nil> TransactionID:} Sender:{User:{ID:@example:example.org cli:<nil>} Room:{ID: cli:<nil>}} Room:{ID: cli:<nil>}}
func (StateEvent) WithClient ¶
func (e StateEvent) WithClient(cli *Client) StateEvent
WithClient sets the underlying client of the RoomEvent. This has to be called after loading the struct from any kind of storage format (e.g JSON). Otherwise calling methods of e.Sender and e.Room will panic at some point
func (StateEvent) WithRoom ¶
func (e StateEvent) WithRoom(room Room) StateEvent
WithRoom sets the originating room of the RoomEvent. This has to be called after loading the struct from any kind of storage format (e.g JSON). Otherwise calling methods of e.Room will panic at some point
type SyncOpts ¶
type SyncOpts struct { // Execute this function if there if an error. If this returns nil, Sync // will sleep for SyncOpts.Timeout and then continue otherwise Sync() // will exit, and return the produced error. OnError func(error) error // Timeout in ms used for long-polling /sync. 3000 is used if this is negative. Timeout int64 }
SyncOpts are optional options to supply to the Sync function
type Thumbnail ¶
type Thumbnail struct { Type string Size int64 Content io.ReadCloser }
Thumbnail represents a thumbnail of content in the content repository. Don't forget to Close() Thumbnail.Content after using it.
type ThumbnailMethod ¶
type ThumbnailMethod string
const ( Crop ThumbnailMethod = "crop" Scale ThumbnailMethod = "scale" )
type ToDeviceEvent ¶
type ToDeviceEvent struct { Type string `json:"type"` Sender User `json:"sender"` Content map[string]interface{} `json:"content"` }
func (ToDeviceEvent) Base ¶
func (e ToDeviceEvent) Base() BaseEvent
func (ToDeviceEvent) Decrypt ¶
func (e ToDeviceEvent) Decrypt() (ToDeviceEvent, error)
Decrypt decrypts the event. The libolm does not support decrypting the same olm message twice. For convenience we cache a copy of the decrypted plaintext internally, so that Decrypt() can be called multiple times. However this cache will be lost, when the underlying client is destroyed. This means, that it is not possible to serialize a encrypted ToDeviceEvent and decrypt it with another instance of Client.
func (ToDeviceEvent) MarshalJSON ¶
func (e ToDeviceEvent) MarshalJSON() ([]byte, error)
Example ¶
e := ToDeviceEvent{ Type: "m.room.key", Content: map[string]interface{}{ "session": 1234, }, Sender: User{ID: "@alice:example.com"}, } out, err := json.Marshal(e) if err != nil { panic(err) } var indent bytes.Buffer json.Indent(&indent, out, "", "\t") indent.WriteTo(os.Stdout)
Output: { "type": "m.room.key", "content": { "session": 1234 }, "sender": "@alice:example.com" }
func (*ToDeviceEvent) UnmarshalJSON ¶
func (e *ToDeviceEvent) UnmarshalJSON(data []byte) error
Example ¶
raw := []byte(` { "content": { "session": "ABCED" }, "type": "m.room.key", "sender": "@alice:example.com" } `) var e ToDeviceEvent err := json.Unmarshal(raw, &e) if err != nil { panic(err) } fmt.Printf("%+v\n", e)
Output: {Type:m.room.key Sender:{ID:@alice:example.com cli:<nil>} Content:map[session:ABCED]}
type User ¶
type User struct { // The matrix ID of the user ID string // contains filtered or unexported fields }
User is matrix User.
func LoadUser ¶
LoadUser tries to find a matrix user. It returns a LogicError if the user does not exist.
func (User) Displayname ¶
Displayname gets the display name of the user by calling the HTTP API.
func (User) Notify ¶
Notify implements the Notifier interface. This can not be used to be notified about ephemeral events relevant for the user (e.g. m.typing events), since it is not possible to attribute all ephemeral events to a certain set of users.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
memory
Package memory contains an in-memory implementation of the Backend interface.
|
Package memory contains an in-memory implementation of the Backend interface. |
examples
|
|
internal
|
|
canonicaljson
Parts of this package have been taken from https://github.com/tulir/mautrix-go/tree/master/crypto/canonicaljson
|
Parts of this package have been taken from https://github.com/tulir/mautrix-go/tree/master/crypto/canonicaljson |
olm
Package olm contains bindings to libolm It was forked from https://github.com/Dhole/go-olm
|
Package olm contains bindings to libolm It was forked from https://github.com/Dhole/go-olm |
util
|
|