events.go 8.6 KB

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