golang-im聊天
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

605 lines
16 KiB

  1. package model
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "gim/internal/logic/domain/message/repo"
  7. "gim/internal/logic/proxy"
  8. "gim/pkg/gerrors"
  9. "gim/pkg/grpclib"
  10. "gim/pkg/logger"
  11. "gim/pkg/pb"
  12. "gim/pkg/rpc"
  13. "gim/pkg/util"
  14. "time"
  15. "go.uber.org/zap"
  16. "google.golang.org/protobuf/proto"
  17. )
  18. const (
  19. UpdateTypeUpdate = 1
  20. UpdateTypeDelete = 2
  21. )
  22. // Group 群组
  23. type Group struct {
  24. Id int64 // 群组id
  25. Name string // 组名
  26. AvatarUrl string // 头像
  27. Introduction string // 群简介
  28. UserNum int32 // 群组人数
  29. IsAllMemberBanned int32 // 是否全员禁言(1:是 2:否)
  30. Extra string // 附加字段
  31. CreateTime time.Time // 创建时间
  32. UpdateTime time.Time // 更新时间
  33. Members []GroupUser `gorm:"-"` // 群组成员
  34. }
  35. type GroupUser struct {
  36. Id int64 // 自增主键
  37. GroupId int64 // 群组id
  38. UserId int64 // 用户id
  39. MemberType int // 群组类型
  40. Remarks string // 备注
  41. Extra string // 附加属性
  42. Status int // 状态
  43. CreateTime time.Time // 创建时间
  44. UpdateTime time.Time // 更新时间
  45. UpdateType int `gorm:"-"` // 更新类型
  46. }
  47. type GroupUserV2 struct {
  48. Id int64 // 自增主键
  49. GroupId int64 // 群组id
  50. UserId int64 // 用户id
  51. MemberType int // 群组类型
  52. Remarks string // 备注
  53. Extra string // 附加属性
  54. Status sql.NullInt32 // 状态
  55. CreateTime time.Time // 创建时间
  56. UpdateTime time.Time // 更新时间
  57. UpdateType int `gorm:"-"` // 更新类型
  58. }
  59. func (g *Group) ToProto() *pb.Group {
  60. if g == nil {
  61. return nil
  62. }
  63. return &pb.Group{
  64. GroupId: g.Id,
  65. Name: g.Name,
  66. AvatarUrl: g.AvatarUrl,
  67. Introduction: g.Introduction,
  68. UserMum: g.UserNum,
  69. IsAllMemberBanned: g.IsAllMemberBanned,
  70. Extra: g.Extra,
  71. CreateTime: g.CreateTime.Unix(),
  72. UpdateTime: g.UpdateTime.Unix(),
  73. }
  74. }
  75. func CreateGroup(userId int64, in *pb.CreateGroupReq) *Group {
  76. now := time.Now()
  77. group := &Group{
  78. Name: in.Name,
  79. AvatarUrl: in.AvatarUrl,
  80. Introduction: in.Introduction,
  81. Extra: in.Extra,
  82. Members: make([]GroupUser, 0, len(in.MemberIds)+1),
  83. CreateTime: now,
  84. UpdateTime: now,
  85. }
  86. // 创建者添加为群主
  87. group.Members = append(group.Members, GroupUser{
  88. GroupId: group.Id,
  89. UserId: userId,
  90. MemberType: int(pb.MemberType_GMT_ADMIN),
  91. CreateTime: now,
  92. UpdateTime: now,
  93. UpdateType: UpdateTypeUpdate,
  94. })
  95. // 其让人添加为成员
  96. for i := range in.MemberIds {
  97. group.Members = append(group.Members, GroupUser{
  98. GroupId: group.Id,
  99. UserId: in.MemberIds[i],
  100. MemberType: int(pb.MemberType_GMT_MEMBER),
  101. CreateTime: now,
  102. UpdateTime: now,
  103. UpdateType: UpdateTypeUpdate,
  104. })
  105. }
  106. return group
  107. }
  108. func (g *Group) Update(ctx context.Context, in *pb.UpdateGroupReq) error {
  109. g.Name = in.Name
  110. g.AvatarUrl = in.AvatarUrl
  111. g.Introduction = in.Introduction
  112. g.Extra = in.Extra
  113. g.UpdateTime = time.Now()
  114. return nil
  115. }
  116. func (g *Group) PushUpdate(ctx context.Context, userId int64, isUpdateIntroduction bool) error {
  117. userResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId})
  118. if err != nil {
  119. return err
  120. }
  121. err = g.PushMessage(ctx, pb.PushCode_PC_UPDATE_GROUP, &pb.UpdateGroupPush{
  122. OptId: userId,
  123. OptName: userResp.User.Nickname,
  124. Name: g.Name,
  125. AvatarUrl: g.AvatarUrl,
  126. Introduction: g.Introduction,
  127. IsUpdateIntroduction: isUpdateIntroduction,
  128. Extra: g.Extra,
  129. }, true)
  130. if err != nil {
  131. return err
  132. }
  133. if isUpdateIntroduction {
  134. //_, err = g.SendMessage(ctx,
  135. // &pb.Sender{
  136. // SenderType: pb.SenderType_ST_USER,
  137. // SenderId: 0,
  138. // },
  139. // &pb.SendMessageReq{
  140. // ReceiverType: pb.ReceiverType_RT_GROUP,
  141. // ReceiverId: g.Id,
  142. // ToUserIds: nil,
  143. // MessageType: pb.MessageType_MT_COMMAND,
  144. // MessageContent: commandBuf,
  145. // SendTime: util.UnixMilliTime(time.Now()),
  146. // IsPersist: isPersist,
  147. // })
  148. //if err != nil {
  149. // return err
  150. //}
  151. }
  152. return nil
  153. }
  154. // SendMessage 消息发送至群组
  155. func (g *Group) SendMessage(ctx context.Context, sender *pb.Sender, req *pb.SendMessageReq) (int64, error) {
  156. if sender.SenderType == pb.SenderType_ST_USER && !g.IsMember(sender.SenderId) {
  157. logger.Sugar.Error(ctx, sender.SenderId, req.ReceiverId, "不在群组内")
  158. return 0, gerrors.ErrNotInGroup
  159. }
  160. // 如果发送者是用户,将消息发送给发送者,获取用户seq
  161. var userSeq int64
  162. var err error
  163. if sender.SenderType == pb.SenderType_ST_USER {
  164. userSeq, err = proxy.MessageProxy.SendToUser(ctx, sender, sender.SenderId, req)
  165. if err != nil {
  166. return 0, err
  167. }
  168. }
  169. go func() {
  170. defer util.RecoverPanic()
  171. // 将消息发送给群组用户,使用写扩散
  172. for _, user := range g.Members {
  173. // 前面已经发送过,这里不需要再发送
  174. if sender.SenderType == pb.SenderType_ST_USER && user.UserId == sender.SenderId {
  175. continue
  176. }
  177. _, err := proxy.MessageProxy.SendToUser(grpclib.NewAndCopyRequestId(ctx), sender, user.UserId, req)
  178. if err != nil {
  179. return
  180. }
  181. }
  182. }()
  183. return userSeq, nil
  184. }
  185. // RecallSendMessage 撤回消息发送至群组
  186. func (g *Group) RecallSendMessage(ctx context.Context, sender *pb.Sender, req *pb.RecallMessageReq) (int64, error) {
  187. if sender.SenderType == pb.SenderType_ST_USER && !g.IsMember(sender.SenderId) {
  188. logger.Sugar.Error(ctx, sender.SenderId, req.ReceiverId, "不在群组内")
  189. return 0, gerrors.ErrNotInGroup
  190. }
  191. var err error
  192. //查询到对应seq的消息
  193. msg := &pb.RECALL{}
  194. err = proto.Unmarshal(req.MessageContent, msg)
  195. if err != nil {
  196. return 0, err
  197. }
  198. message, err := repo.MessageRepo.GetMessage(sender.SenderId, msg.RecallSeq)
  199. if err != nil {
  200. return 0, err
  201. }
  202. // 如果发送者是用户,将消息发送给发送者,获取用户seq
  203. var userSeq int64
  204. if sender.SenderType == pb.SenderType_ST_USER {
  205. userSeq, err = proxy.MessageProxy.RecallMessageSendToUser(ctx, sender, sender.SenderId, req, message.SendTime)
  206. if err != nil {
  207. return 0, err
  208. }
  209. }
  210. go func() {
  211. defer util.RecoverPanic()
  212. // 将消息发送给群组用户,使用写扩散
  213. for _, user := range g.Members {
  214. // 前面已经发送过,这里不需要再发送
  215. if sender.SenderType == pb.SenderType_ST_USER && user.UserId == sender.SenderId {
  216. continue
  217. }
  218. msg.RecallSeq, err = repo.MessageRepo.GetMessageSeqForSendTime(user.UserId, message.SendTime)
  219. req.MessageContent, err = proto.Marshal(msg)
  220. if err != nil {
  221. return
  222. }
  223. _, err := proxy.MessageProxy.RecallMessageSendToUser(grpclib.NewAndCopyRequestId(ctx), sender, user.UserId, req, message.SendTime)
  224. if err != nil {
  225. return
  226. }
  227. }
  228. }()
  229. return userSeq, nil
  230. }
  231. // SendRedPackage 发送红包消息发送至群组
  232. func (g *Group) SendRedPackage(ctx context.Context, sender *pb.Sender, req *pb.SendRedPacketReq) (int64, error) {
  233. if sender.SenderType == pb.SenderType_ST_USER && !g.IsMember(sender.SenderId) {
  234. logger.Sugar.Error(ctx, sender.SenderId, req.ReceiverId, "不在群组内")
  235. return 0, gerrors.ErrNotInGroup
  236. }
  237. // 如果发送者是用户,将消息发送给发送者,获取用户seq
  238. var userSeq int64
  239. var err error
  240. if sender.SenderType == pb.SenderType_ST_USER {
  241. userSeq, err = proxy.MessageProxy.SendRedPackageToUser(ctx, sender, sender.SenderId, req)
  242. if err != nil {
  243. return 0, err
  244. }
  245. }
  246. go func() {
  247. defer util.RecoverPanic()
  248. // 将消息发送给群组用户,使用写扩散
  249. for _, user := range g.Members {
  250. // 前面已经发送过,这里不需要再发送
  251. if sender.SenderType == pb.SenderType_ST_USER && user.UserId == sender.SenderId {
  252. continue
  253. }
  254. _, err := proxy.MessageProxy.SendRedPackageToUser(grpclib.NewAndCopyRequestId(ctx), sender, user.UserId, req)
  255. if err != nil {
  256. return
  257. }
  258. }
  259. }()
  260. return userSeq, nil
  261. }
  262. func (g *Group) IsMember(userId int64) bool {
  263. for i := range g.Members {
  264. if g.Members[i].UserId == userId {
  265. return true
  266. }
  267. }
  268. return false
  269. }
  270. // PushMessage 向群组推送消息
  271. func (g *Group) PushMessage(ctx context.Context, code pb.PushCode, message proto.Message, isPersist bool) error {
  272. logger.Logger.Debug("push_to_group",
  273. zap.Int64("request_id", grpclib.GetCtxRequestId(ctx)),
  274. zap.Int64("group_id", g.Id),
  275. zap.Int32("code", int32(code)),
  276. zap.Any("message", message))
  277. messageBuf, err := proto.Marshal(message)
  278. if err != nil {
  279. return gerrors.WrapError(err)
  280. }
  281. commandBuf, err := proto.Marshal(&pb.Command{Code: int32(code), Data: messageBuf})
  282. if err != nil {
  283. return gerrors.WrapError(err)
  284. }
  285. _, err = g.SendMessage(ctx,
  286. &pb.Sender{
  287. SenderType: pb.SenderType_ST_SYSTEM,
  288. SenderId: 0,
  289. },
  290. &pb.SendMessageReq{
  291. ReceiverType: pb.ReceiverType_RT_GROUP,
  292. ReceiverId: g.Id,
  293. ToUserIds: nil,
  294. MessageType: pb.MessageType_MT_COMMAND,
  295. MessageContent: commandBuf,
  296. SendTime: util.UnixMilliTime(time.Now()),
  297. IsPersist: isPersist,
  298. },
  299. )
  300. if err != nil {
  301. return err
  302. }
  303. return nil
  304. }
  305. // GetMembers 获取群组用户
  306. func (g *Group) GetMembers(ctx context.Context) ([]*pb.GroupMember, error) {
  307. members := g.Members
  308. userIds := make(map[int64]int32, len(members))
  309. for i := range members {
  310. userIds[members[i].UserId] = 0
  311. }
  312. resp, err := rpc.GetBusinessIntClient().GetUsers(ctx, &pb.GetUsersReq{UserIds: userIds})
  313. if err != nil {
  314. return nil, err
  315. }
  316. var infos = make([]*pb.GroupMember, len(members))
  317. for i := range members {
  318. member := pb.GroupMember{
  319. UserId: members[i].UserId,
  320. MemberType: pb.MemberType(members[i].MemberType),
  321. Remarks: members[i].Remarks,
  322. Extra: members[i].Extra,
  323. Status: int32(members[i].Status),
  324. }
  325. user, ok := resp.Users[members[i].UserId]
  326. if ok {
  327. member.Nickname = user.Nickname
  328. member.Sex = user.Sex
  329. member.AvatarUrl = user.AvatarUrl
  330. member.UserExtra = user.Extra
  331. }
  332. infos[i] = &member
  333. }
  334. return infos, nil
  335. }
  336. // AddMembers 给群组添加用户
  337. func (g *Group) AddMembers(ctx context.Context, userIds []int64) ([]int64, []int64, error) {
  338. var existIds []int64
  339. var addedIds []int64
  340. now := time.Now()
  341. for i, userId := range userIds {
  342. if g.IsMember(userId) {
  343. existIds = append(existIds, userIds[i])
  344. continue
  345. }
  346. g.Members = append(g.Members, GroupUser{
  347. GroupId: g.Id,
  348. UserId: userIds[i],
  349. MemberType: int(pb.MemberType_GMT_MEMBER),
  350. CreateTime: now,
  351. UpdateTime: now,
  352. UpdateType: UpdateTypeUpdate,
  353. })
  354. addedIds = append(addedIds, userIds[i])
  355. }
  356. g.UserNum += int32(len(addedIds))
  357. return existIds, addedIds, nil
  358. }
  359. func (g *Group) PushAddMember(ctx context.Context, optUserId int64, addedIds []int64) error {
  360. var addIdMap = make(map[int64]int32, len(addedIds))
  361. for i := range addedIds {
  362. addIdMap[addedIds[i]] = 0
  363. }
  364. addIdMap[optUserId] = 0
  365. usersResp, err := rpc.GetBusinessIntClient().GetUsers(ctx, &pb.GetUsersReq{UserIds: addIdMap})
  366. if err != nil {
  367. return err
  368. }
  369. var members []*pb.GroupMember
  370. for k, _ := range addIdMap {
  371. member, ok := usersResp.Users[k]
  372. if !ok {
  373. continue
  374. }
  375. members = append(members, &pb.GroupMember{
  376. UserId: member.UserId,
  377. Nickname: member.Nickname,
  378. Sex: member.Sex,
  379. AvatarUrl: member.AvatarUrl,
  380. UserExtra: member.Extra,
  381. Remarks: "",
  382. Extra: "",
  383. })
  384. }
  385. //
  386. optUser := usersResp.Users[optUserId]
  387. if optUserId == -1 {
  388. optUser.Nickname = "后台操作"
  389. }
  390. err = g.PushMessage(ctx, pb.PushCode_PC_ADD_GROUP_MEMBERS, &pb.AddGroupMembersPush{
  391. OptId: optUser.UserId,
  392. OptName: optUser.Nickname,
  393. Members: members,
  394. }, true)
  395. if err != nil {
  396. logger.Sugar.Error(err)
  397. }
  398. return nil
  399. }
  400. func (g *Group) GetMember(ctx context.Context, userId int64) *GroupUser {
  401. for i := range g.Members {
  402. if g.Members[i].UserId == userId {
  403. return &g.Members[i]
  404. }
  405. }
  406. return nil
  407. }
  408. // UpdateMember 更新群组成员信息
  409. func (g *Group) UpdateMember(ctx context.Context, in *pb.UpdateGroupMemberReq) error {
  410. member := g.GetMember(ctx, in.UserId)
  411. if member == nil {
  412. return nil
  413. }
  414. member.MemberType = int(in.MemberType)
  415. member.Remarks = in.Remarks
  416. member.Extra = in.Extra
  417. member.UpdateTime = time.Now()
  418. member.UpdateType = UpdateTypeUpdate
  419. return nil
  420. }
  421. // DeleteMember 删除用户群组
  422. func (g *Group) DeleteMember(ctx context.Context, userId int64) error {
  423. member := g.GetMember(ctx, userId)
  424. if member == nil {
  425. return nil
  426. }
  427. member.UpdateType = UpdateTypeDelete
  428. return nil
  429. }
  430. func (g *Group) PushUpdateMember(ctx context.Context, optId, userId int64, memberType int32) error {
  431. userResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: optId})
  432. if err != nil {
  433. return err
  434. }
  435. if optId == -1 {
  436. userResp.User.Nickname = "后台操作"
  437. }
  438. updateUserResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId})
  439. if err != nil {
  440. return err
  441. }
  442. err = g.PushMessage(ctx, pb.PushCode_PC_UPDATE_GROUP_MEMBER, &pb.UpdateMemberPush{
  443. OptId: optId,
  444. OptName: userResp.User.Nickname,
  445. UpdateUserId: userId,
  446. UpdateUserName: updateUserResp.User.Nickname,
  447. UpdateUserMemberType: memberType,
  448. }, true)
  449. if err != nil {
  450. return err
  451. }
  452. return nil
  453. }
  454. func (g *Group) PushDeleteMember(ctx context.Context, optId, userId int64) error {
  455. userResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: optId})
  456. if err != nil {
  457. return err
  458. }
  459. if optId == -1 {
  460. userResp.User.Nickname = "后台操作"
  461. }
  462. deleteUserResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId})
  463. if err != nil {
  464. return err
  465. }
  466. err = g.PushMessage(ctx, pb.PushCode_PC_REMOVE_GROUP_MEMBER, &pb.RemoveGroupMemberPush{
  467. OptId: optId,
  468. OptName: userResp.User.Nickname,
  469. DeletedUserId: userId,
  470. DeletedUserName: deleteUserResp.User.Nickname,
  471. }, true)
  472. if err != nil {
  473. return err
  474. }
  475. return nil
  476. }
  477. func (g *Group) PushGroupMemberBanned(ctx context.Context, optId, userId int64, isAllMemberBanned bool) error {
  478. userResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: optId})
  479. if err != nil {
  480. return err
  481. }
  482. if optId == -1 {
  483. userResp.User.Nickname = "后台操作"
  484. }
  485. if !isAllMemberBanned && userId > 0 {
  486. bannedUserResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId})
  487. if err != nil {
  488. return err
  489. }
  490. err = g.PushMessage(ctx, pb.PushCode_PC_BANNED_GROUP_MEMBER, &pb.BannedGroupMemberPush{
  491. OptId: optId,
  492. OptName: userResp.User.Nickname,
  493. BannedUserId: userId,
  494. BannedUserName: bannedUserResp.User.Nickname,
  495. }, true)
  496. if err != nil {
  497. return err
  498. }
  499. return nil
  500. } else {
  501. if userId == 0 {
  502. err = g.PushMessage(ctx, pb.PushCode_PC_BANNED_GROUP_MEMBER, &pb.BannedGroupMemberPush{
  503. OptId: optId,
  504. OptName: userResp.User.Nickname,
  505. BannedUserId: userId,
  506. BannedUserName: fmt.Sprintf("管理员\"%s\"设置群禁言", userResp.User.Nickname),
  507. }, true)
  508. if err != nil {
  509. return err
  510. }
  511. } else {
  512. err = g.PushMessage(ctx, pb.PushCode_PC_BANNED_GROUP_MEMBER, &pb.BannedGroupMemberPush{
  513. OptId: optId,
  514. OptName: userResp.User.Nickname,
  515. BannedUserId: userId,
  516. BannedUserName: fmt.Sprintf("管理员\"%s\"取消群禁言", userResp.User.Nickname),
  517. }, true)
  518. if err != nil {
  519. return err
  520. }
  521. }
  522. return nil
  523. }
  524. }
  525. func (g *Group) PushGroupMemberRemoveBanned(ctx context.Context, optId, userId int64) error {
  526. userResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: optId})
  527. if err != nil {
  528. return err
  529. }
  530. if optId == -1 {
  531. userResp.User.Nickname = "后台操作"
  532. }
  533. removeBannedUserResp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId})
  534. if err != nil {
  535. return err
  536. }
  537. err = g.PushMessage(ctx, pb.PushCode_PC_REMOVE_BANNED_GROUP_MEMBER, &pb.RemoveBannedGroupMemberPush{
  538. OptId: optId,
  539. OptName: userResp.User.Nickname,
  540. RemoveBannedUserId: userId,
  541. RemoveBannedUserName: removeBannedUserResp.User.Nickname,
  542. }, true)
  543. if err != nil {
  544. return err
  545. }
  546. return nil
  547. }