message.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package server
  2. import (
  3. "encoding"
  4. "encoding/json"
  5. "github.com/mitchellh/mapstructure"
  6. "github.com/rotisserie/eris"
  7. "go.uber.org/zap"
  8. )
  9. type MessageType = int8
  10. type ChatingContentType = uint8
  11. const (
  12. MessageTypeError MessageType = -1 // MessageTypeError 错误消息,当服务器出现错误时,会发送此消息
  13. MessageTypePingPong MessageType = 1 // MessageTypePingPong ping pong 消息
  14. MessageTypeEmpty MessageType = 2 // MessageTypeEmpty 空消息
  15. MessageTypeUpChating MessageType = 30 // MessageTypeUpChating 语聊消息
  16. MessageTypeDownChating MessageType = 31 // MessageTypeDownChating 语聊消息
  17. MessageTypeNotification MessageType = 40 // MessageTypeNotification 通知消息
  18. MessageTypeLocation MessageType = 50 // MessageTypeLocation 定位类型
  19. MessageTypeVideoCall MessageType = 60 // MessageTypeVideoCall 视频通话来电
  20. )
  21. const (
  22. ChatingContentTypeText ChatingContentType = 1 + iota // ChatingContentTypeText 语聊文字消息
  23. ChatingContentTypeMetadata // ChatingContentTypeMetadata 媒体文件消息
  24. )
  25. const (
  26. NotificationTypeDeviceStatusChange = 100 // NotificationTypeDeviceStatusChange 设备绑定状态变更通知
  27. NotificationTypeAskLocation = 111 // NotificationTypeAskLocation 询问设备位置
  28. NotificationTypeChangedContacts = 130 // NotificationTypeChangedContacts 联系人变动通知
  29. NotificationTypeCreatedFriend = 120 // NotificationTypeCreatedFriend 通知添加好友结果通知
  30. NotificationTypeChangedAlarmClock = 140 // NotificationTypeChangedAlarmClock 闹钟变更通知
  31. NotificationTypeChangedSchoolMode = 141 // NotificationTypeChangedSchoolMode 上课禁用变更通知
  32. NotificationTypeDeviceShutdown = 150 // NotificationTypeDeviceShutdown 设备关机通知
  33. NotificationTypeDeviceReboot = 160 // NotificationTypeDeviceReboot 设备重启通知
  34. )
  35. var _ encoding.BinaryMarshaler = (*Message)(nil)
  36. var _ encoding.BinaryUnmarshaler = (*Message)(nil)
  37. type Message struct {
  38. MessageId string `json:"-"` // MessageId 消息Id, 不参与序列化
  39. sender string `json:"-"` // sender 消息发送者, 给内部使用, 不参与序列化
  40. Type MessageType `json:"type"`
  41. RequestId string `json:"requestId"` // RequestId 当前消息的Id
  42. Content any `json:"content"` // Content 内容
  43. Receiver string `json:"receiver,omitempty"` // Receiver 消息接受者
  44. }
  45. type FirebaseMessage struct {
  46. token string
  47. message *Message
  48. // clt *Client
  49. }
  50. type (
  51. // ChatingContent to client chating message
  52. ChatingContent struct {
  53. MessageId string `json:"messageId" mapstructure:"messageId"`
  54. Receiver string `json:"receiver" mapstructure:"receiver"`
  55. SessionId string `json:"sessionId" mapstructure:"sessionId"` // SessionId 过度字段, 一般和 Receiver 内容相同
  56. PayloadType ChatingContentType `json:"payloadType" mapstructure:"payloadType"`
  57. Payload any `json:"payload" mapstructure:"payload"`
  58. SendTime int64 `json:"sendTime" mapstructure:"sendTime"`
  59. }
  60. // NotificationContent to client notice message
  61. NotificationContent struct {
  62. ID int `json:"id" mapstructure:"id"`
  63. Payload map[string]interface{} `json:"payload" mapstructure:"payload"`
  64. }
  65. LocationMessageContent struct {
  66. Longitude string `json:"lng" mapstructure:"lng"` // Longitude 纬度
  67. Latitude string `json:"lat" mapstructure:"lat"` // Latitude 经度
  68. Radius int `json:"radius" mapstructure:"radius"` // Radius 精度
  69. ChildrenId string `json:"cid" mapstructure:"cid"` // ChildrenId 孩子ID
  70. Type string `json:"type" mapstructure:"type"` // Type 类型
  71. PositionTime int64 `json:"positionTime" mapstructure:"positionTime"` // PositionTime 时间
  72. }
  73. VideoCallMessageContent struct {
  74. AccountId string `json:"accountId" mapstructure:"accountId"` // AccountId 账号ID
  75. }
  76. )
  77. type (
  78. // ContentText received a text message from the client
  79. ContentText struct {
  80. Raw string `json:"raw" mapstructure:"raw"`
  81. }
  82. // ContentMetadata received media file message from client
  83. ContentMetadata struct {
  84. Url string `json:"url" mapstructure:""` // Url 文件地址
  85. FileType string `json:"fileType" mapstructure:""` // FileType 文件类型
  86. Duration uint `json:"duration" mapstructure:""` // Duration 视频/语音时长
  87. }
  88. // ContentReply content to be replied to after receiving the message
  89. ContentReply struct {
  90. MessageId string `json:"messageId" mapstructure:"messageId"`
  91. }
  92. // ContentError an error occurred while processing the message
  93. ContentError struct {
  94. Err string `json:"err" mapstructure:"err"`
  95. }
  96. )
  97. func (m *Message) UnmarshalBinary(data []byte) error {
  98. return json.Unmarshal(data, m)
  99. }
  100. func (m *Message) MarshalBinary() (data []byte, err error) {
  101. return json.Marshal(m)
  102. }
  103. func (m *Message) IsNeedReply() bool {
  104. return m.RequestId != ""
  105. }
  106. func (m *Message) IsError() bool {
  107. return m.Type == MessageTypeError
  108. }
  109. func (m *Message) String() string {
  110. buf, _ := m.MarshalBinary()
  111. return string(buf)
  112. }
  113. func deserializeMessage(bytes []byte) *Message {
  114. if len(bytes) == 0 {
  115. return emptyMessage()
  116. }
  117. var message Message
  118. err := json.Unmarshal(bytes, &message)
  119. if err != nil {
  120. zap.L().Error("[message] unable to deserialize message", zap.Error(err))
  121. return emptyMessage()
  122. }
  123. switch message.Type {
  124. // Is it a chating message
  125. case MessageTypeUpChating, MessageTypeDownChating:
  126. var chatingContent ChatingContent
  127. if err := mapstructure.Decode(message.Content, &chatingContent); err != nil {
  128. return errorMessage(message.RequestId, eris.Wrap(err, "failed to decode chating content"))
  129. }
  130. message.Content = chatingContent
  131. // Is it a notify message
  132. case MessageTypeNotification:
  133. var notificationContent NotificationContent
  134. if err := mapstructure.Decode(message.Content, &notificationContent); err != nil {
  135. return errorMessage(message.RequestId, eris.Wrap(err, "failed to decode notify content"))
  136. }
  137. message.Content = notificationContent
  138. // Is it a location message
  139. case MessageTypeLocation:
  140. var locationMessageContent LocationMessageContent
  141. if err := mapstructure.Decode(message.Content, &locationMessageContent); err != nil {
  142. return errorMessage(message.RequestId, eris.Wrap(err, "failed to decode location content"))
  143. }
  144. message.Content = locationMessageContent
  145. // Message without content
  146. case MessageTypeVideoCall:
  147. var videoCallMessageContent VideoCallMessageContent
  148. if err := mapstructure.Decode(message.Content, &videoCallMessageContent); err != nil {
  149. return errorMessage(message.RequestId, eris.Wrap(err, "failed to decode video call content"))
  150. }
  151. message.Content = videoCallMessageContent
  152. }
  153. return &message
  154. }
  155. func serializationMessage(message *Message) []byte {
  156. // Erases some fields that are not needed for the client
  157. message.Receiver = ""
  158. // Serializable
  159. bytes, _ := json.Marshal(message)
  160. return bytes
  161. }
  162. // newReplyMessage new a to client reply message
  163. func newReplyMessage(message *Message) *Message {
  164. switch message.Type {
  165. case MessageTypePingPong:
  166. message.Content = "pong"
  167. case MessageTypeUpChating:
  168. message.Content = &ContentReply{MessageId: message.MessageId}
  169. }
  170. return message
  171. }
  172. func emptyMessage() *Message {
  173. return &Message{Type: MessageTypeEmpty}
  174. }
  175. func errorMessage(requestId string, err error) *Message {
  176. return &Message{
  177. Type: MessageTypeError,
  178. RequestId: requestId,
  179. Content: err.Error(),
  180. }
  181. }