diff --git a/hs-im-server/im-common/src/main/java/com/lld/im/common/model/ChatHistoryReq.java b/hs-im-server/im-common/src/main/java/com/lld/im/common/model/ChatHistoryReq.java new file mode 100644 index 0000000..70d5b2a --- /dev/null +++ b/hs-im-server/im-common/src/main/java/com/lld/im/common/model/ChatHistoryReq.java @@ -0,0 +1,24 @@ +package com.lld.im.common.model; + +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class ChatHistoryReq extends RequestBase { + private static final long serialVersionUID = 1L; + + + private String operater; + + private String userId; + + + //单次拉取数量 + private Integer limit; + + //第几页 + private Integer offset; +} diff --git a/hs-im-server/im-service/src/main/java/com/lld/im/service/message/controller/MessageController.java b/hs-im-server/im-service/src/main/java/com/lld/im/service/message/controller/MessageController.java index b78a79a..4e7fb3b 100644 --- a/hs-im-server/im-service/src/main/java/com/lld/im/service/message/controller/MessageController.java +++ b/hs-im-server/im-service/src/main/java/com/lld/im/service/message/controller/MessageController.java @@ -1,9 +1,11 @@ package com.lld.im.service.message.controller; import com.lld.im.common.ResponseVO; +import com.lld.im.common.model.ChatHistoryReq; import com.lld.im.common.model.SyncReq; import com.lld.im.common.model.message.CheckSendMessageReq; import com.lld.im.service.message.model.req.SendMessageReq; +import com.lld.im.service.message.model.resp.ImMessageHistoryVo; import com.lld.im.service.message.service.MessageSyncService; import com.lld.im.service.message.service.P2PMessageService; import org.springframework.beans.factory.annotation.Autowired; @@ -12,6 +14,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + /** * @description: * @author: lld @@ -46,7 +50,33 @@ public class MessageController { return messageSyncService.syncOfflineMessage(req); } + /** + * 获取会话列表 + * @param req + * @param appId + * @return + */ + @RequestMapping("/listMessage") + public ResponseVO listMessage(@RequestBody + @Validated SyncReq req, Integer appId) { + req.setAppId(appId); + List objects = messageSyncService.listSession(req); + return null; + } + /** + * 获取会话列表 + * @param req + * @param appId + * @return + */ + @RequestMapping("/chatHistory") + public ResponseVO chatHistory(@RequestBody + @Validated ChatHistoryReq chatHistoryReq, Integer appId) { + chatHistoryReq.setAppId(appId); + List imMessageHistoryVos = messageSyncService.chatHistory(chatHistoryReq); + return ResponseVO.successResponse(imMessageHistoryVos); + } diff --git a/hs-im-server/im-service/src/main/java/com/lld/im/service/message/model/resp/ImMessageHistoryVo.java b/hs-im-server/im-service/src/main/java/com/lld/im/service/message/model/resp/ImMessageHistoryVo.java new file mode 100644 index 0000000..c30664f --- /dev/null +++ b/hs-im-server/im-service/src/main/java/com/lld/im/service/message/model/resp/ImMessageHistoryVo.java @@ -0,0 +1,15 @@ +package com.lld.im.service.message.model.resp; + +import com.lld.im.service.message.dao.ImMessageHistoryEntity; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class ImMessageHistoryVo extends ImMessageHistoryEntity { + + private String messageBody; + +} diff --git a/hs-im-server/im-service/src/main/java/com/lld/im/service/message/service/MessageSyncService.java b/hs-im-server/im-service/src/main/java/com/lld/im/service/message/service/MessageSyncService.java index 15c9691..cfcf2ce 100644 --- a/hs-im-server/im-service/src/main/java/com/lld/im/service/message/service/MessageSyncService.java +++ b/hs-im-server/im-service/src/main/java/com/lld/im/service/message/service/MessageSyncService.java @@ -1,11 +1,12 @@ package com.lld.im.service.message.service; import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.lld.im.codec.pack.message.MessageReadedPack; import com.lld.im.codec.pack.message.RecallMessageNotifyPack; -import com.lld.im.codec.proto.Message; import com.lld.im.common.ResponseVO; import com.lld.im.common.constant.Constants; import com.lld.im.common.enums.ConversationTypeEnum; @@ -14,6 +15,7 @@ import com.lld.im.common.enums.MessageErrorCode; import com.lld.im.common.enums.command.Command; import com.lld.im.common.enums.command.GroupEventCommand; import com.lld.im.common.enums.command.MessageCommand; +import com.lld.im.common.model.ChatHistoryReq; import com.lld.im.common.model.ClientInfo; import com.lld.im.common.model.SyncReq; import com.lld.im.common.model.SyncResp; @@ -24,12 +26,13 @@ import com.lld.im.common.model.message.RecallMessageContent; import com.lld.im.service.conversation.service.ConversationService; import com.lld.im.service.group.service.ImGroupMemberService; import com.lld.im.service.message.dao.ImMessageBodyEntity; +import com.lld.im.service.message.dao.ImMessageHistoryEntity; import com.lld.im.service.message.dao.mapper.ImMessageBodyMapper; +import com.lld.im.service.message.dao.mapper.ImMessageHistoryMapper; +import com.lld.im.service.message.model.resp.ImMessageHistoryVo; import com.lld.im.service.seq.RedisSeq; -import com.lld.im.service.utils.ConversationIdGenerate; -import com.lld.im.service.utils.GroupMessageProducer; -import com.lld.im.service.utils.MessageProducer; -import com.lld.im.service.utils.SnowflakeIdWorker; +import com.lld.im.service.utils.*; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.DefaultTypedTuple; @@ -39,7 +42,9 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * @description: @@ -73,6 +78,8 @@ public class MessageSyncService { @Autowired GroupMessageProducer groupMessageProducer; + @Autowired + private ImMessageHistoryMapper imMessageHistoryMapper; public void receiveMark(MessageReciveAckContent messageReciveAckContent){ messageProducer.sendToUser(messageReciveAckContent.getToId(), @@ -156,6 +163,103 @@ public class MessageSyncService { return ResponseVO.successResponse(resp); } + public List listSession(SyncReq req){ + List listOfflineMessage = listOfflineMessage(req); + + List listReadMessage = listReadMessage(req); + Map collect = listReadMessage.stream().collect(Collectors.toMap(ImMessageHistoryEntity::getOwnerId, ImMessageHistoryEntity::getMessageKey)); + + return null; + } + + public List chatHistory(ChatHistoryReq chatHistoryReq){ + Page objectPage = new Page<>(chatHistoryReq.getOffset(),chatHistoryReq.getLimit()); + LambdaQueryWrapper and = new LambdaQueryWrapper().eq(ImMessageHistoryEntity::getOwnerId, chatHistoryReq.getOperater()) + .and(x -> x.eq(ImMessageHistoryEntity::getFromId, chatHistoryReq.getUserId()).or().eq(ImMessageHistoryEntity::getToId, chatHistoryReq.getUserId())) + .orderByDesc(ImMessageHistoryEntity::getMessageKey); + Page imMessageHistoryEntities = imMessageHistoryMapper.selectPage(objectPage,and); + List messageKeys = imMessageHistoryEntities.getRecords().stream().map(x -> x.getMessageKey()).collect(Collectors.toList()); + List imMessageBodyEntities = imMessageBodyMapper.selectList(new LambdaQueryWrapper().in(ImMessageBodyEntity::getMessageKey, messageKeys)); + Map collect = imMessageBodyEntities.stream().collect(Collectors.toMap(ImMessageBodyEntity::getMessageKey, x -> x)); + + List imMessageHistoryVos = BeanCopyUtils.copyList(imMessageHistoryEntities.getRecords(), ImMessageHistoryVo.class); + for (ImMessageHistoryVo imMessageHistoryVo : imMessageHistoryVos) { + ImMessageBodyEntity imMessageBodyEntity = collect.get(imMessageHistoryVo.getMessageKey()); + imMessageHistoryVo.setMessageBody(imMessageBodyEntity.getMessageBody()); + } + return imMessageHistoryVos; + } + + + /** + * 获取离线消息 + * @param req + * @return + */ + public List listOfflineMessage(SyncReq req) { + String key = req.getAppId() + ":" + Constants.RedisConstants.OfflineMessage + ":" + req.getOperater(); + //获取最大的seq + Long maxSeq = 0L; + ZSetOperations zSetOperations = redisTemplate.opsForZSet(); + Set set = zSetOperations.reverseRangeWithScores(key, 0, 0); + if(!CollectionUtils.isEmpty(set)){ + List list = new ArrayList(set); + DefaultTypedTuple o = (DefaultTypedTuple) list.get(0); + maxSeq = o.getScore().longValue(); + } + + List respList = new ArrayList<>(); + + Set querySet = zSetOperations.rangeByScoreWithScores(key, + req.getLastSequence(), maxSeq, 0, -1); + for (ZSetOperations.TypedTuple typedTuple : querySet) { + String value = typedTuple.getValue(); + OfflineMessageContent offlineMessageContent = JSONObject.parseObject(value, OfflineMessageContent.class); + respList.add(offlineMessageContent); + } + +// +// List imMessageBodyIds = new ArrayList<>(); +// Map toIdMap = respList.stream().collect(Collectors.toMap(OfflineMessageContent::getToId, x -> x)); +// Map> toIdMap2 = respList.stream(). +// collect(Collectors.groupingBy(x -> x.getFromId() + "-"+ x.getToId(),Collectors.maxBy(Comparator.comparingLong(OfflineMessageContent::getMessageKey)))); +// for (OfflineMessageContent offlineMessageContent : respList) { +// OfflineMessageContent messageKey1 = toIdMap.get(offlineMessageContent.getToId()); +// if (messageKey1 != null){ +// imMessageBodyIds.add(messageKey1.getMessageKey() > offlineMessageContent.getMessageKey() ? messageKey1 : offlineMessageContent); +// } +// } + + return respList; + } + + /** + * 获取已读消息 + * @param req + * @return + */ + public List listReadMessage(SyncReq req) { + List imMessageHistoryEntities = imMessageHistoryMapper.selectMessageByOwnId(req.getOperater()); + List imMessageBodyIds = new ArrayList<>(); + + Map fromIdMap = imMessageHistoryEntities.stream() + .filter(x -> !StringUtils.equals(x.getFromId(),req.getOperater())) + .collect(Collectors.toMap(ImMessageHistoryEntity::getFromId, ImMessageHistoryEntity::getMessageKey)); + Map toIdMap = imMessageHistoryEntities.stream() + .filter(x -> !StringUtils.equals(x.getToId(),req.getOperater())) + .collect(Collectors.toMap(ImMessageHistoryEntity::getToId, ImMessageHistoryEntity::getMessageKey)); + fromIdMap.forEach((key,value) -> { + toIdMap.merge(key,value,(x,y) -> { + if (value > y) return value; + return y; + }); + }); + + List imMessageBodyEntities = imMessageBodyMapper.selectList(new LambdaQueryWrapper().in(ImMessageBodyEntity::getMessageKey, imMessageBodyIds)); + + return null; + } + //修改历史消息的状态 //修改离线消息的状态 //ack给发送方