123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- package gomatrix
- import (
- "encoding/json"
- "sync"
- )
- type EventType struct {
- Type string
- IsState bool
- }
- func (et *EventType) UnmarshalJSON(data []byte) error {
- err := json.Unmarshal(data, &et.Type)
- if err != nil {
- return err
- }
- switch et.Type {
- case StateAliases.Type, StateCanonicalAlias.Type, StateCreate.Type, StateJoinRules.Type, StateMember.Type,
- StatePowerLevels.Type, StateRoomName.Type, StateRoomAvatar.Type, StateTopic.Type, StatePinnedEvents.Type:
- et.IsState = true
- default:
- et.IsState = false
- }
- return nil
- }
- func (et *EventType) MarshalJSON() ([]byte, error) {
- return json.Marshal(&et.Type)
- }
- func (et *EventType) String() string {
- return et.Type
- }
- type MessageType string
- // State events
- var (
- StateAliases = EventType{"m.room.aliases", true}
- StateCanonicalAlias = EventType{"m.room.canonical_alias", true}
- StateCreate = EventType{"m.room.create", true}
- StateJoinRules = EventType{"m.room.join_rules", true}
- StateMember = EventType{"m.room.member", true}
- StatePowerLevels = EventType{"m.room.power_levels", true}
- StateRoomName = EventType{"m.room.name", true}
- StateTopic = EventType{"m.room.topic", true}
- StateRoomAvatar = EventType{"m.room.avatar", true}
- StatePinnedEvents = EventType{"m.room.pinned_events", true}
- )
- // Message events
- var (
- EventRedaction = EventType{"m.room.redaction", false}
- EventMessage = EventType{"m.room.message", false}
- EventSticker = EventType{"m.sticker", false}
- )
- // Msgtypes
- const (
- MsgText MessageType = "m.text"
- MsgEmote = "m.emote"
- MsgNotice = "m.notice"
- MsgImage = "m.image"
- MsgLocation = "m.location"
- MsgVideo = "m.video"
- MsgAudio = "m.audio"
- MsgFile = "m.file"
- )
- type Format string
- // Message formats
- const (
- FormatHTML Format = "org.matrix.custom.html"
- )
- // 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 EventType `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 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 {
- if evt.StateKey != nil {
- return *evt.StateKey
- }
- 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"`
- ReplacesState string `json:"replaces_state,omitempty"`
- Age int64 `json:"age,omitempty"`
- }
- type Content struct {
- VeryRaw json.RawMessage `json:"-"`
- Raw map[string]interface{} `json:"-"`
- MsgType MessageType `json:"msgtype,omitempty"`
- Body string `json:"body,omitempty"`
- Format Format `json:"format,omitempty"`
- FormattedBody string `json:"formatted_body,omitempty"`
- 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
- RoomName
- RoomTopic
- }
- type serializableContent Content
- func (content *Content) UnmarshalJSON(data []byte) error {
- content.VeryRaw = data
- if err := json.Unmarshal(data, &content.Raw); err != nil {
- return err
- }
- return json.Unmarshal(data, (*serializableContent)(content))
- }
- 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{}
- }
- return content.Info
- }
- type RoomName struct {
- Name string `json:"name,omitempty"`
- }
- type RoomTopic struct {
- Topic string `json:"topic,omitempty"`
- }
- 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 {
- usersLock sync.RWMutex `json:"-"`
- Users map[string]int `json:"users,omitempty"`
- UsersDefault int `json:"users_default,omitempty"`
- eventsLock sync.RWMutex `json:"-"`
- Events map[string]int `json:"events,omitempty"`
- EventsDefault int `json:"events_default,omitempty"`
- StateDefaultPtr *int `json:"state_default,omitempty"`
- InvitePtr *int `json:"invite,omitempty"`
- KickPtr *int `json:"kick,omitempty"`
- BanPtr *int `json:"ban,omitempty"`
- RedactPtr *int `json:"redact,omitempty"`
- }
- func (pl *PowerLevels) Invite() int {
- if pl.InvitePtr != nil {
- return *pl.InvitePtr
- }
- return 50
- }
- func (pl *PowerLevels) Kick() int {
- if pl.KickPtr != nil {
- return *pl.KickPtr
- }
- return 50
- }
- func (pl *PowerLevels) Ban() int {
- if pl.BanPtr != nil {
- return *pl.BanPtr
- }
- return 50
- }
- func (pl *PowerLevels) Redact() int {
- if pl.RedactPtr != nil {
- return *pl.RedactPtr
- }
- return 50
- }
- func (pl *PowerLevels) StateDefault() int {
- if pl.StateDefaultPtr != nil {
- return *pl.StateDefaultPtr
- }
- return 50
- }
- func (pl *PowerLevels) GetUserLevel(userID string) int {
- pl.usersLock.RLock()
- defer pl.usersLock.RUnlock()
- level, ok := pl.Users[userID]
- if !ok {
- return pl.UsersDefault
- }
- return level
- }
- func (pl *PowerLevels) SetUserLevel(userID string, level int) {
- pl.usersLock.Lock()
- defer pl.usersLock.Unlock()
- if level == pl.UsersDefault {
- delete(pl.Users, userID)
- } else {
- pl.Users[userID] = level
- }
- }
- 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) int {
- pl.eventsLock.RLock()
- defer pl.eventsLock.RUnlock()
- level, ok := pl.Events[eventType.String()]
- if !ok {
- if eventType.IsState {
- return pl.StateDefault()
- }
- return pl.EventsDefault
- }
- return level
- }
- func (pl *PowerLevels) SetEventLevel(eventType EventType, level int) {
- pl.eventsLock.Lock()
- defer pl.eventsLock.Unlock()
- if (eventType.IsState && level == pl.StateDefault()) || (!eventType.IsState && level == pl.EventsDefault) {
- delete(pl.Events, eventType.String())
- } else {
- pl.Events[eventType.String()] = level
- }
- }
- func (pl *PowerLevels) EnsureEventLevel(eventType EventType, level int) bool {
- existingLevel := pl.GetEventLevel(eventType)
- if existingLevel != level {
- pl.SetEventLevel(eventType, level)
- return true
- }
- return false
- }
- type FileInfo struct {
- MimeType string `json:"mimetype,omitempty"`
- ThumbnailInfo *FileInfo `json:"thumbnail_info,omitempty"`
- ThumbnailURL string `json:"thumbnail_url,omitempty"`
- Height int `json:"h,omitempty"`
- Width int `json:"w,omitempty"`
- Duration uint `json:"duration,omitempty"`
- Size int `json:"size,omitempty"`
- }
- func (fileInfo *FileInfo) GetThumbnailInfo() *FileInfo {
- if fileInfo.ThumbnailInfo == nil {
- fileInfo.ThumbnailInfo = &FileInfo{}
- }
- return fileInfo.ThumbnailInfo
- }
- type RelatesTo struct {
- InReplyTo InReplyTo `json:"m.in_reply_to,omitempty"`
- }
- type InReplyTo struct {
- EventID string `json:"event_id,omitempty"`
- // Not required, just for future-proofing
- RoomID string `json:"room_id,omitempty"`
- }
|