- 实现IM API接口定义,包括消息、群组、好友、黑名单等功能 - 定义IM消息相关数据模型,包含聊天类型、消息类型、用户资料等 - 实现ImSDK单例类,提供登录、消息发送、群组管理、好友管理等核心功能 - 添加WebSocket连接管理,支持自动重连机制 - 实现历史消息查询、群组操作、用户资料管理等API调用 - 添加会话状态管理,支持置顶、静音、草稿等功能 - 集成文件上传结果,支持多媒体消息发送 - 实现连接状态监听和事件回调机制
244 行
10 KiB
Java
244 行
10 KiB
Java
package com.xuqm.im.service;
|
||
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||
import com.xuqm.common.exception.BusinessException;
|
||
import com.xuqm.im.cluster.ImClusterPublisher;
|
||
import com.xuqm.im.entity.ImFriendRequestEntity;
|
||
import com.xuqm.im.entity.ImMessageEntity;
|
||
import com.xuqm.im.repository.ImFriendRequestRepository;
|
||
import com.xuqm.im.repository.ImFriendRepository;
|
||
import com.xuqm.im.repository.ImMessageRepository;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.transaction.annotation.Transactional;
|
||
|
||
import java.time.LocalDateTime;
|
||
import java.util.List;
|
||
import java.util.UUID;
|
||
|
||
@Service
|
||
public class FriendRequestService {
|
||
|
||
private final ImFriendRequestRepository requestRepository;
|
||
private final ImFriendRepository friendRepository;
|
||
private final ImMessageRepository messageRepository;
|
||
private final ImClusterPublisher clusterPublisher;
|
||
private final ObjectMapper objectMapper;
|
||
|
||
public FriendRequestService(ImFriendRequestRepository requestRepository,
|
||
ImFriendRepository friendRepository,
|
||
ImMessageRepository messageRepository,
|
||
ImClusterPublisher clusterPublisher,
|
||
ObjectMapper objectMapper) {
|
||
this.requestRepository = requestRepository;
|
||
this.friendRepository = friendRepository;
|
||
this.messageRepository = messageRepository;
|
||
this.clusterPublisher = clusterPublisher;
|
||
this.objectMapper = objectMapper;
|
||
}
|
||
|
||
@Transactional
|
||
public ImFriendRequestEntity send(String appId, String fromUserId, String toUserId, String remark) {
|
||
ImFriendRequestEntity saved = requestRepository.findByAppIdAndFromUserIdAndToUserId(appId, fromUserId, toUserId)
|
||
.orElseGet(() -> {
|
||
ImFriendRequestEntity entity = new ImFriendRequestEntity();
|
||
entity.setId(UUID.randomUUID().toString());
|
||
entity.setAppId(appId);
|
||
entity.setFromUserId(fromUserId);
|
||
entity.setToUserId(toUserId);
|
||
entity.setRemark(remark);
|
||
entity.setStatus(ImFriendRequestEntity.Status.PENDING.name());
|
||
entity.setCreatedAt(LocalDateTime.now());
|
||
return requestRepository.save(entity);
|
||
});
|
||
if (!ImFriendRequestEntity.Status.PENDING.name().equals(saved.getStatus())) {
|
||
return saved;
|
||
}
|
||
publishNotification(
|
||
saved,
|
||
saved.getFromUserId(),
|
||
saved.getToUserId(),
|
||
"FRIEND_REQUEST",
|
||
"好友申请",
|
||
buildDescription("好友申请", saved.getRemark())
|
||
);
|
||
return saved;
|
||
}
|
||
|
||
@Transactional
|
||
public ImFriendRequestEntity accept(String appId, String requestId, String operatorId) {
|
||
ImFriendRequestEntity request = getRequest(appId, requestId, operatorId);
|
||
request.setStatus(ImFriendRequestEntity.Status.ACCEPTED.name());
|
||
request.setReviewedAt(LocalDateTime.now());
|
||
requestRepository.save(request);
|
||
friendRepository
|
||
.findByAppIdAndUserIdAndFriendId(appId, request.getFromUserId(), request.getToUserId())
|
||
.orElseGet(() -> friendEntity(appId, request.getFromUserId(), request.getToUserId()));
|
||
friendRepository
|
||
.findByAppIdAndUserIdAndFriendId(appId, request.getToUserId(), request.getFromUserId())
|
||
.orElseGet(() -> friendEntity(appId, request.getToUserId(), request.getFromUserId()));
|
||
publishNotification(
|
||
request,
|
||
request.getToUserId(),
|
||
request.getFromUserId(),
|
||
"FRIEND_REQUEST_STATUS",
|
||
"好友申请已通过",
|
||
buildDescription("好友申请已通过", request.getRemark())
|
||
);
|
||
return request;
|
||
}
|
||
|
||
@Transactional
|
||
public ImFriendRequestEntity reject(String appId, String requestId, String operatorId) {
|
||
ImFriendRequestEntity request = getRequest(appId, requestId, operatorId);
|
||
request.setStatus(ImFriendRequestEntity.Status.REJECTED.name());
|
||
request.setReviewedAt(LocalDateTime.now());
|
||
ImFriendRequestEntity saved = requestRepository.save(request);
|
||
publishNotification(
|
||
saved,
|
||
saved.getToUserId(),
|
||
saved.getFromUserId(),
|
||
"FRIEND_REQUEST_STATUS",
|
||
"好友申请已拒绝",
|
||
buildDescription("好友申请已拒绝", saved.getRemark())
|
||
);
|
||
return saved;
|
||
}
|
||
|
||
@Transactional
|
||
public List<ImFriendRequestEntity> acceptBatch(String appId, List<String> requestIds, String operatorId) {
|
||
List<ImFriendRequestEntity> result = new java.util.ArrayList<>();
|
||
for (String requestId : unique(requestIds)) {
|
||
result.add(acceptInternal(appId, requestId, operatorId));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
@Transactional
|
||
public List<ImFriendRequestEntity> rejectBatch(String appId, List<String> requestIds, String operatorId) {
|
||
List<ImFriendRequestEntity> result = new java.util.ArrayList<>();
|
||
for (String requestId : unique(requestIds)) {
|
||
result.add(rejectInternal(appId, requestId, operatorId));
|
||
}
|
||
return result;
|
||
}
|
||
|
||
public List<ImFriendRequestEntity> incoming(String appId, String userId) {
|
||
return requestRepository.findByAppIdAndToUserId(appId, userId).stream()
|
||
.filter(request -> ImFriendRequestEntity.Status.PENDING.name().equals(request.getStatus()))
|
||
.toList();
|
||
}
|
||
|
||
public List<ImFriendRequestEntity> outgoing(String appId, String userId) {
|
||
return requestRepository.findByAppIdAndFromUserId(appId, userId);
|
||
}
|
||
|
||
private ImFriendRequestEntity getRequest(String appId, String requestId, String operatorId) {
|
||
ImFriendRequestEntity request = requestRepository.findById(requestId)
|
||
.orElseThrow(() -> new BusinessException(404, "好友申请不存在"));
|
||
if (!request.getAppId().equals(appId) || !request.getToUserId().equals(operatorId)) {
|
||
throw new BusinessException(403, "无权操作");
|
||
}
|
||
return request;
|
||
}
|
||
|
||
private ImFriendRequestEntity acceptInternal(String appId, String requestId, String operatorId) {
|
||
ImFriendRequestEntity request = getRequest(appId, requestId, operatorId);
|
||
request.setStatus(ImFriendRequestEntity.Status.ACCEPTED.name());
|
||
request.setReviewedAt(LocalDateTime.now());
|
||
ImFriendRequestEntity saved = requestRepository.save(request);
|
||
friendRepository
|
||
.findByAppIdAndUserIdAndFriendId(appId, request.getFromUserId(), request.getToUserId())
|
||
.orElseGet(() -> friendEntity(appId, request.getFromUserId(), request.getToUserId()));
|
||
friendRepository
|
||
.findByAppIdAndUserIdAndFriendId(appId, request.getToUserId(), request.getFromUserId())
|
||
.orElseGet(() -> friendEntity(appId, request.getToUserId(), request.getFromUserId()));
|
||
publishNotification(
|
||
request,
|
||
request.getToUserId(),
|
||
request.getFromUserId(),
|
||
"FRIEND_REQUEST_STATUS",
|
||
"好友申请已通过",
|
||
buildDescription("好友申请已通过", request.getRemark())
|
||
);
|
||
return saved;
|
||
}
|
||
|
||
private ImFriendRequestEntity rejectInternal(String appId, String requestId, String operatorId) {
|
||
ImFriendRequestEntity request = getRequest(appId, requestId, operatorId);
|
||
request.setStatus(ImFriendRequestEntity.Status.REJECTED.name());
|
||
request.setReviewedAt(LocalDateTime.now());
|
||
ImFriendRequestEntity saved = requestRepository.save(request);
|
||
publishNotification(
|
||
saved,
|
||
saved.getToUserId(),
|
||
saved.getFromUserId(),
|
||
"FRIEND_REQUEST_STATUS",
|
||
"好友申请已拒绝",
|
||
buildDescription("好友申请已拒绝", saved.getRemark())
|
||
);
|
||
return saved;
|
||
}
|
||
|
||
private com.xuqm.im.entity.ImFriendEntity friendEntity(String appId, String userId, String friendId) {
|
||
com.xuqm.im.entity.ImFriendEntity entity = new com.xuqm.im.entity.ImFriendEntity();
|
||
entity.setAppId(appId);
|
||
entity.setUserId(userId);
|
||
entity.setFriendId(friendId);
|
||
return friendRepository.save(entity);
|
||
}
|
||
|
||
private List<String> unique(List<String> requestIds) {
|
||
return requestIds == null ? List.of() : new java.util.ArrayList<>(new java.util.LinkedHashSet<>(requestIds));
|
||
}
|
||
|
||
private void publishNotification(
|
||
ImFriendRequestEntity request,
|
||
String fromUserId,
|
||
String toUserId,
|
||
String type,
|
||
String title,
|
||
String content
|
||
) {
|
||
ImMessageEntity message = new ImMessageEntity();
|
||
message.setId(UUID.randomUUID().toString());
|
||
message.setAppId(request.getAppId());
|
||
message.setFromUserId(fromUserId);
|
||
message.setToId(toUserId);
|
||
message.setChatType(ImMessageEntity.ChatType.SINGLE);
|
||
message.setMsgType(ImMessageEntity.MsgType.NOTIFY);
|
||
message.setContent(buildNotificationContent(type, title, content, request));
|
||
message.setStatus(ImMessageEntity.MsgStatus.SENT);
|
||
message.setCreatedAt(LocalDateTime.now());
|
||
ImMessageEntity saved = messageRepository.save(message);
|
||
clusterPublisher.publish("/user/" + toUserId + "/queue/messages", saved);
|
||
}
|
||
|
||
private String buildNotificationContent(
|
||
String type,
|
||
String title,
|
||
String content,
|
||
ImFriendRequestEntity request
|
||
) {
|
||
ObjectNode node = objectMapper.createObjectNode();
|
||
node.put("type", type);
|
||
node.put("title", title);
|
||
node.put("content", content);
|
||
node.put("requestId", request.getId());
|
||
node.put("fromUserId", request.getFromUserId());
|
||
node.put("toUserId", request.getToUserId());
|
||
node.put("status", request.getStatus());
|
||
if (request.getRemark() != null) {
|
||
node.put("remark", request.getRemark());
|
||
}
|
||
return node.toString();
|
||
}
|
||
|
||
private String buildDescription(String prefix, String remark) {
|
||
if (remark == null || remark.isBlank()) {
|
||
return prefix;
|
||
}
|
||
return prefix + ":" + remark;
|
||
}
|
||
}
|