events.go 8.9 KB

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