golang-im聊天
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

365 linhas
8.8 KiB

  1. package model
  2. import (
  3. "context"
  4. "gim/internal/logic/proxy"
  5. "gim/pkg/gerrors"
  6. "gim/pkg/grpclib"
  7. "gim/pkg/logger"
  8. "gim/pkg/pb"
  9. "gim/pkg/rpc"
  10. "gim/pkg/util"
  11. "time"
  12. "go.uber.org/zap"
  13. "google.golang.org/protobuf/proto"
  14. )
  15. const (
  16. UpdateTypeUpdate = 1
  17. UpdateTypeDelete = 2
  18. )
  19. // Group 群组
  20. type Group struct {
  21. Id int64 // 群组id
  22. Name string // 组名
  23. AvatarUrl string // 头像
  24. Introduction string // 群简介
  25. UserNum int32 // 群组人数
  26. Extra string // 附加字段
  27. CreateTime time.Time // 创建时间
  28. UpdateTime time.Time // 更新时间
  29. Members []GroupUser `gorm:"-"` // 群组成员
  30. }
  31. type GroupUser struct {
  32. Id int64 // 自增主键
  33. GroupId int64 // 群组id
  34. UserId int64 // 用户id
  35. MemberType int // 群组类型
  36. Remarks string // 备注
  37. Extra string // 附加属性
  38. Status int // 状态
  39. CreateTime time.Time // 创建时间
  40. UpdateTime time.Time // 更新时间
  41. UpdateType int `gorm:"-"` // 更新类型
  42. }
  43. func (g *Group) ToProto() *pb.Group {
  44. if g == nil {
  45. return nil
  46. }
  47. return &pb.Group{
  48. GroupId: g.Id,
  49. Name: g.Name,
  50. AvatarUrl: g.AvatarUrl,
  51. Introduction: g.Introduction,
  52. UserMum: g.UserNum,
  53. Extra: g.Extra,
  54. CreateTime: g.CreateTime.Unix(),
  55. UpdateTime: g.UpdateTime.Unix(),
  56. }
  57. }
  58. func CreateGroup(userId int64, in *pb.CreateGroupReq) *Group {
  59. now := time.Now()
  60. group := &Group{
  61. Name: in.Name,
  62. AvatarUrl: in.AvatarUrl,
  63. Introduction: in.Introduction,
  64. Extra: in.Extra,
  65. Members: make([]GroupUser, 0, len(in.MemberIds)+1),
  66. CreateTime: now,
  67. UpdateTime: now,
  68. }
  69. // 创建者添加为管理员
  70. group.Members = append(group.Members, GroupUser{
  71. GroupId: group.Id,
  72. UserId: userId,
  73. MemberType: int(pb.MemberType_GMT_ADMIN),
  74. CreateTime: now,
  75. UpdateTime: now,
  76. UpdateType: UpdateTypeUpdate,
  77. })
  78. // 其让人添加为成员
  79. for i := range in.MemberIds {
  80. group.Members = append(group.Members, GroupUser{
  81. GroupId: group.Id,
  82. UserId: in.MemberIds[i],
  83. MemberType: int(pb.MemberType_GMT_MEMBER),
  84. CreateTime: now,
  85. UpdateTime: now,
  86. UpdateType: UpdateTypeUpdate,
  87. })
  88. }
  89. return group
  90. }
  91. func (g *Group) Update(ctx context.Context, in *pb.UpdateGroupReq) error {
  92. g.Name = in.Name
  93. g.AvatarUrl = in.AvatarUrl
  94. g.Introduction = in.Introduction
  95. g.Extra = in.Extra
  96. return nil
  97. }
  98. func (g *Group) PushUpdate(ctx context.Context, userId int64) error {
  99. userResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId})
  100. if err != nil {
  101. return err
  102. }
  103. err = g.PushMessage(ctx, pb.PushCode_PC_UPDATE_GROUP, &pb.UpdateGroupPush{
  104. OptId: userId,
  105. OptName: userResp.User.Nickname,
  106. Name: g.Name,
  107. AvatarUrl: g.AvatarUrl,
  108. Introduction: g.Introduction,
  109. Extra: g.Extra,
  110. }, true)
  111. if err != nil {
  112. return err
  113. }
  114. return nil
  115. }
  116. // SendMessage 消息发送至群组
  117. func (g *Group) SendMessage(ctx context.Context, sender *pb.Sender, req *pb.SendMessageReq) (int64, error) {
  118. if sender.SenderType == pb.SenderType_ST_USER && !g.IsMember(sender.SenderId) {
  119. logger.Sugar.Error(ctx, sender.SenderId, req.ReceiverId, "不在群组内")
  120. return 0, gerrors.ErrNotInGroup
  121. }
  122. // 如果发送者是用户,将消息发送给发送者,获取用户seq
  123. var userSeq int64
  124. var err error
  125. if sender.SenderType == pb.SenderType_ST_USER {
  126. userSeq, err = proxy.MessageProxy.SendToUser(ctx, sender, sender.SenderId, req)
  127. if err != nil {
  128. return 0, err
  129. }
  130. }
  131. go func() {
  132. defer util.RecoverPanic()
  133. // 将消息发送给群组用户,使用写扩散
  134. for _, user := range g.Members {
  135. // 前面已经发送过,这里不需要再发送
  136. if sender.SenderType == pb.SenderType_ST_USER && user.UserId == sender.SenderId {
  137. continue
  138. }
  139. _, err := proxy.MessageProxy.SendToUser(grpclib.NewAndCopyRequestId(ctx), sender, user.UserId, req)
  140. if err != nil {
  141. return
  142. }
  143. }
  144. }()
  145. return userSeq, nil
  146. }
  147. func (g *Group) IsMember(userId int64) bool {
  148. for i := range g.Members {
  149. if g.Members[i].UserId == userId {
  150. return true
  151. }
  152. }
  153. return false
  154. }
  155. // PushMessage 向群组推送消息
  156. func (g *Group) PushMessage(ctx context.Context, code pb.PushCode, message proto.Message, isPersist bool) error {
  157. logger.Logger.Debug("push_to_group",
  158. zap.Int64("request_id", grpclib.GetCtxRequestId(ctx)),
  159. zap.Int64("group_id", g.Id),
  160. zap.Int32("code", int32(code)),
  161. zap.Any("message", message))
  162. messageBuf, err := proto.Marshal(message)
  163. if err != nil {
  164. return gerrors.WrapError(err)
  165. }
  166. commandBuf, err := proto.Marshal(&pb.Command{Code: int32(code), Data: messageBuf})
  167. if err != nil {
  168. return gerrors.WrapError(err)
  169. }
  170. _, err = g.SendMessage(ctx,
  171. &pb.Sender{
  172. SenderType: pb.SenderType_ST_SYSTEM,
  173. SenderId: 0,
  174. },
  175. &pb.SendMessageReq{
  176. ReceiverType: pb.ReceiverType_RT_GROUP,
  177. ReceiverId: g.Id,
  178. ToUserIds: nil,
  179. MessageType: pb.MessageType_MT_COMMAND,
  180. MessageContent: commandBuf,
  181. SendTime: util.UnixMilliTime(time.Now()),
  182. IsPersist: isPersist,
  183. },
  184. )
  185. if err != nil {
  186. return err
  187. }
  188. return nil
  189. }
  190. // GetMembers 获取群组用户
  191. func (g *Group) GetMembers(ctx context.Context) ([]*pb.GroupMember, error) {
  192. members := g.Members
  193. userIds := make(map[int64]int32, len(members))
  194. for i := range members {
  195. userIds[members[i].UserId] = 0
  196. }
  197. resp, err := rpc.GetBusinessIntClient().GetUsers(ctx, &pb.GetUsersReq{UserIds: userIds})
  198. if err != nil {
  199. return nil, err
  200. }
  201. var infos = make([]*pb.GroupMember, len(members))
  202. for i := range members {
  203. member := pb.GroupMember{
  204. UserId: members[i].UserId,
  205. MemberType: pb.MemberType(members[i].MemberType),
  206. Remarks: members[i].Remarks,
  207. Extra: members[i].Extra,
  208. }
  209. user, ok := resp.Users[members[i].UserId]
  210. if ok {
  211. member.Nickname = user.Nickname
  212. member.Sex = user.Sex
  213. member.AvatarUrl = user.AvatarUrl
  214. member.UserExtra = user.Extra
  215. }
  216. infos[i] = &member
  217. }
  218. return infos, nil
  219. }
  220. // AddMembers 给群组添加用户
  221. func (g *Group) AddMembers(ctx context.Context, userIds []int64) ([]int64, []int64, error) {
  222. var existIds []int64
  223. var addedIds []int64
  224. now := time.Now()
  225. for i, userId := range userIds {
  226. if g.IsMember(userId) {
  227. existIds = append(existIds, userIds[i])
  228. continue
  229. }
  230. g.Members = append(g.Members, GroupUser{
  231. GroupId: g.Id,
  232. UserId: userIds[i],
  233. MemberType: int(pb.MemberType_GMT_MEMBER),
  234. CreateTime: now,
  235. UpdateTime: now,
  236. UpdateType: UpdateTypeUpdate,
  237. })
  238. addedIds = append(addedIds, userIds[i])
  239. }
  240. g.UserNum += int32(len(addedIds))
  241. return existIds, addedIds, nil
  242. }
  243. func (g *Group) PushAddMember(ctx context.Context, optUserId int64, addedIds []int64) error {
  244. var addIdMap = make(map[int64]int32, len(addedIds))
  245. for i := range addedIds {
  246. addIdMap[addedIds[i]] = 0
  247. }
  248. addIdMap[optUserId] = 0
  249. usersResp, err := rpc.GetBusinessIntClient().GetUsers(ctx, &pb.GetUsersReq{UserIds: addIdMap})
  250. if err != nil {
  251. return err
  252. }
  253. var members []*pb.GroupMember
  254. for k, _ := range addIdMap {
  255. member, ok := usersResp.Users[k]
  256. if !ok {
  257. continue
  258. }
  259. members = append(members, &pb.GroupMember{
  260. UserId: member.UserId,
  261. Nickname: member.Nickname,
  262. Sex: member.Sex,
  263. AvatarUrl: member.AvatarUrl,
  264. UserExtra: member.Extra,
  265. Remarks: "",
  266. Extra: "",
  267. })
  268. }
  269. optUser := usersResp.Users[optUserId]
  270. err = g.PushMessage(ctx, pb.PushCode_PC_ADD_GROUP_MEMBERS, &pb.AddGroupMembersPush{
  271. OptId: optUser.UserId,
  272. OptName: optUser.Nickname,
  273. Members: members,
  274. }, true)
  275. if err != nil {
  276. logger.Sugar.Error(err)
  277. }
  278. return nil
  279. }
  280. func (g *Group) GetMember(ctx context.Context, userId int64) *GroupUser {
  281. for i := range g.Members {
  282. if g.Members[i].UserId == userId {
  283. return &g.Members[i]
  284. }
  285. }
  286. return nil
  287. }
  288. // UpdateMember 更新群组成员信息
  289. func (g *Group) UpdateMember(ctx context.Context, in *pb.UpdateGroupMemberReq) error {
  290. member := g.GetMember(ctx, in.UserId)
  291. if member == nil {
  292. return nil
  293. }
  294. member.MemberType = int(in.MemberType)
  295. member.Remarks = in.Remarks
  296. member.Extra = in.Extra
  297. member.UpdateTime = time.Now()
  298. member.UpdateType = UpdateTypeUpdate
  299. return nil
  300. }
  301. // DeleteMember 删除用户群组
  302. func (g *Group) DeleteMember(ctx context.Context, userId int64) error {
  303. member := g.GetMember(ctx, userId)
  304. if member == nil {
  305. return nil
  306. }
  307. member.UpdateType = UpdateTypeDelete
  308. return nil
  309. }
  310. func (g *Group) PushDeleteMember(ctx context.Context, optId, userId int64) error {
  311. userResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: optId})
  312. if err != nil {
  313. return err
  314. }
  315. err = g.PushMessage(ctx, pb.PushCode_PC_REMOVE_GROUP_MEMBER, &pb.RemoveGroupMemberPush{
  316. OptId: optId,
  317. OptName: userResp.User.Nickname,
  318. DeletedUserId: userId,
  319. }, true)
  320. if err != nil {
  321. return err
  322. }
  323. return nil
  324. }