events.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package gomatrix
  2. import (
  3. "encoding/json"
  4. "sync"
  5. )
  6. type EventType string
  7. type MessageType string
  8. // State events
  9. const (
  10. StateAliases EventType = "m.room.aliases"
  11. StateCanonicalAlias = "m.room.canonical_alias"
  12. StateCreate = "m.room.create"
  13. StateJoinRules = "m.room.join_rules"
  14. StateMember = "m.room.member"
  15. StatePowerLevels = "m.room.power_levels"
  16. StateRoomName = "m.room.name"
  17. StateTopic = "m.room.topic"
  18. StateRoomAvatar = "m.room.avatar"
  19. StatePinnedEvents = "m.room.pinned_events"
  20. )
  21. // Message events
  22. const (
  23. EventRedaction EventType = "m.room.redaction"
  24. EventMessage = "m.room.message"
  25. EventSticker = "m.sticker"
  26. )
  27. // Msgtypes
  28. const (
  29. MsgText MessageType = "m.text"
  30. MsgEmote = "m.emote"
  31. MsgNotice = "m.notice"
  32. MsgImage = "m.image"
  33. MsgLocation = "m.location"
  34. MsgVideo = "m.video"
  35. MsgAudio = "m.audio"
  36. MsgFile = "m.file"
  37. )
  38. type Format string
  39. // Message formats
  40. const (
  41. FormatHTML Format = "org.matrix.custom.html"
  42. )
  43. // Event represents a single Matrix event.
  44. type Event struct {
  45. StateKey *string `json:"state_key,omitempty"` // The state key for the event. Only present on State Events.
  46. Sender string `json:"sender"` // The user ID of the sender of the event
  47. Type EventType `json:"type"` // The event type
  48. Timestamp int64 `json:"origin_server_ts"` // The unix timestamp when this message was sent by the origin server
  49. ID string `json:"event_id"` // The unique ID of this event
  50. RoomID string `json:"room_id"` // The room the event was sent to. May be nil (e.g. for presence)
  51. Content Content `json:"content"` // The JSON content of the event.
  52. Redacts string `json:"redacts,omitempty"` // The event ID that was redacted if a m.room.redaction event
  53. Unsigned Unsigned `json:"unsigned,omitempty"` // Unsigned content set by own homeserver.
  54. InviteRoomState []StrippedState `json:"invite_room_state"`
  55. }
  56. func (evt *Event) GetStateKey() string {
  57. if evt.StateKey != nil {
  58. return *evt.StateKey
  59. }
  60. return ""
  61. }
  62. type StrippedState struct {
  63. Content Content `json:"content"`
  64. Type EventType `json:"type"`
  65. StateKey string `json:"state_key"`
  66. }
  67. type Unsigned struct {
  68. PrevContent map[string]interface{} `json:"prev_content,omitempty"`
  69. PrevSender string `json:"prev_sender,omitempty"`
  70. ReplacesState string `json:"replaces_state,omitempty"`
  71. Age int64 `json:"age,omitempty"`
  72. }
  73. type Content struct {
  74. VeryRaw json.RawMessage `json:"-"`
  75. Raw map[string]interface{} `json:"-"`
  76. MsgType MessageType `json:"msgtype,omitempty"`
  77. Body string `json:"body,omitempty"`
  78. Format Format `json:"format,omitempty"`
  79. FormattedBody string `json:"formatted_body,omitempty"`
  80. Info *FileInfo `json:"info,omitempty"`
  81. URL string `json:"url,omitempty"`
  82. // Membership key for easy access in m.room.member events
  83. Membership string `json:"membership,omitempty"`
  84. RelatesTo *RelatesTo `json:"m.relates_to,omitempty"`
  85. PowerLevels
  86. Member
  87. Aliases
  88. CanonicalAlias
  89. RoomName
  90. RoomTopic
  91. }
  92. type serializableContent Content
  93. func (content *Content) UnmarshalJSON(data []byte) error {
  94. content.VeryRaw = data
  95. if err := json.Unmarshal(data, &content.Raw); err != nil {
  96. return err
  97. }
  98. return json.Unmarshal(data, (*serializableContent)(content))
  99. }
  100. func (content *Content) UnmarshalPowerLevels() (pl PowerLevels, err error) {
  101. err = json.Unmarshal(content.VeryRaw, &pl)
  102. return
  103. }
  104. func (content *Content) UnmarshalMember() (m Member, err error) {
  105. err = json.Unmarshal(content.VeryRaw, &m)
  106. return
  107. }
  108. func (content *Content) UnmarshalAliases() (a Aliases, err error) {
  109. err = json.Unmarshal(content.VeryRaw, &a)
  110. return
  111. }
  112. func (content *Content) UnmarshalCanonicalAlias() (ca CanonicalAlias, err error) {
  113. err = json.Unmarshal(content.VeryRaw, &ca)
  114. return
  115. }
  116. func (content *Content) GetInfo() *FileInfo {
  117. if content.Info == nil {
  118. content.Info = &FileInfo{}
  119. }
  120. return content.Info
  121. }
  122. type RoomName struct {
  123. Name string `json:"name,omitempty"`
  124. }
  125. type RoomTopic struct {
  126. Topic string `json:"topic,omitempty"`
  127. }
  128. type Member struct {
  129. Membership string `json:"membership,omitempty"`
  130. AvatarURL string `json:"avatar_url,omitempty"`
  131. Displayname string `json:"displayname,omitempty"`
  132. ThirdPartyInvite *ThirdPartyInvite `json:"third_party_invite,omitempty"`
  133. }
  134. type ThirdPartyInvite struct {
  135. DisplayName string `json:"display_name"`
  136. Signed struct {
  137. Token string `json:"token"`
  138. Signatures json.RawMessage `json:"signatures"`
  139. MXID string `json:"mxid"`
  140. }
  141. }
  142. type Aliases struct {
  143. Aliases []string `json:"aliases,omitempty"`
  144. }
  145. type CanonicalAlias struct {
  146. Alias string `json:"alias,omitempty"`
  147. }
  148. type PowerLevels struct {
  149. usersLock sync.RWMutex `json:"-"`
  150. Users map[string]int `json:"users,omitempty"`
  151. UsersDefault int `json:"users_default,omitempty"`
  152. eventsLock sync.RWMutex `json:"-"`
  153. Events map[EventType]int `json:"events,omitempty"`
  154. EventsDefault int `json:"events_default,omitempty"`
  155. StateDefaultPtr *int `json:"state_default,omitempty"`
  156. InvitePtr *int `json:"invite,omitempty"`
  157. KickPtr *int `json:"kick,omitempty"`
  158. BanPtr *int `json:"ban,omitempty"`
  159. RedactPtr *int `json:"redact,omitempty"`
  160. }
  161. func (pl *PowerLevels) Invite() int {
  162. if pl.InvitePtr != nil {
  163. return *pl.InvitePtr
  164. }
  165. return 50
  166. }
  167. func (pl *PowerLevels) Kick() int {
  168. if pl.KickPtr != nil {
  169. return *pl.KickPtr
  170. }
  171. return 50
  172. }
  173. func (pl *PowerLevels) Ban() int {
  174. if pl.BanPtr != nil {
  175. return *pl.BanPtr
  176. }
  177. return 50
  178. }
  179. func (pl *PowerLevels) Redact() int {
  180. if pl.RedactPtr != nil {
  181. return *pl.RedactPtr
  182. }
  183. return 50
  184. }
  185. func (pl *PowerLevels) StateDefault() int {
  186. if pl.StateDefaultPtr != nil {
  187. return *pl.StateDefaultPtr
  188. }
  189. return 50
  190. }
  191. func (pl *PowerLevels) GetUserLevel(userID string) int {
  192. pl.usersLock.RLock()
  193. defer pl.usersLock.RUnlock()
  194. level, ok := pl.Users[userID]
  195. if !ok {
  196. return pl.UsersDefault
  197. }
  198. return level
  199. }
  200. func (pl *PowerLevels) SetUserLevel(userID string, level int) {
  201. pl.usersLock.Lock()
  202. defer pl.usersLock.Unlock()
  203. if level == pl.UsersDefault {
  204. delete(pl.Users, userID)
  205. } else {
  206. pl.Users[userID] = level
  207. }
  208. }
  209. func (pl *PowerLevels) EnsureUserLevel(userID string, level int) bool {
  210. existingLevel := pl.GetUserLevel(userID)
  211. if existingLevel != level {
  212. pl.SetUserLevel(userID, level)
  213. return true
  214. }
  215. return false
  216. }
  217. func (pl *PowerLevels) GetEventLevel(eventType EventType, isState bool) int {
  218. pl.eventsLock.RLock()
  219. defer pl.eventsLock.RUnlock()
  220. level, ok := pl.Events[eventType]
  221. if !ok {
  222. if isState {
  223. return pl.StateDefault()
  224. }
  225. return pl.EventsDefault
  226. }
  227. return level
  228. }
  229. func (pl *PowerLevels) SetEventLevel(eventType EventType, isState bool, level int) {
  230. pl.eventsLock.Lock()
  231. defer pl.eventsLock.Unlock()
  232. if (isState && level == pl.StateDefault()) || (!isState && level == pl.EventsDefault) {
  233. delete(pl.Events, eventType)
  234. } else {
  235. pl.Events[eventType] = level
  236. }
  237. }
  238. func (pl *PowerLevels) EnsureEventLevel(eventType EventType, isState bool, level int) bool {
  239. existingLevel := pl.GetEventLevel(eventType, isState)
  240. if existingLevel != level {
  241. pl.SetEventLevel(eventType, isState, level)
  242. return true
  243. }
  244. return false
  245. }
  246. type FileInfo struct {
  247. MimeType string `json:"mimetype,omitempty"`
  248. ThumbnailInfo *FileInfo `json:"thumbnail_info,omitempty"`
  249. ThumbnailURL string `json:"thumbnail_url,omitempty"`
  250. Height int `json:"h,omitempty"`
  251. Width int `json:"w,omitempty"`
  252. Duration uint `json:"duration,omitempty"`
  253. Size int `json:"size,omitempty"`
  254. }
  255. func (fileInfo *FileInfo) GetThumbnailInfo() *FileInfo {
  256. if fileInfo.ThumbnailInfo == nil {
  257. fileInfo.ThumbnailInfo = &FileInfo{}
  258. }
  259. return fileInfo.ThumbnailInfo
  260. }
  261. type RelatesTo struct {
  262. InReplyTo InReplyTo `json:"m.in_reply_to,omitempty"`
  263. }
  264. type InReplyTo struct {
  265. EventID string `json:"event_id,omitempty"`
  266. // Not required, just for future-proofing
  267. RoomID string `json:"room_id,omitempty"`
  268. }