This commit is contained in:
dute7liang
2024-01-11 23:38:56 +08:00
parent f7485b9066
commit 728192d4f0
21 changed files with 231 additions and 58 deletions

View File

@@ -20,6 +20,7 @@ import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.constant.RedisConstant; import com.ruoyi.cai.ws.constant.RedisConstant;
import com.ruoyi.cai.ws.dto.WsToken; import com.ruoyi.cai.ws.dto.WsToken;
import com.ruoyi.cai.ws.manager.WebSocketManager; import com.ruoyi.cai.ws.manager.WebSocketManager;
import com.ruoyi.cai.ws.util.MapGetUtil;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.helper.LoginHelper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -30,6 +31,7 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -56,14 +58,29 @@ public class ChatManager {
String token = IdManager.nextIdStr(); String token = IdManager.nextIdStr();
String tokenKey = String.format(RedisConstant.WS_TOKEN, token); String tokenKey = String.format(RedisConstant.WS_TOKEN, token);
Map<String,Object> map = new HashMap<>(); Map<String,Object> map = new HashMap<>();
map.put("userId",userId);
map.put("roomId",roomId); map.put("roomId",roomId);
map.put("fromUid",fromUid); map.put("fromUid",fromUid);
map.put("toUid",toUid); map.put("toUid",toUid);
map.put("userId",userId);
redisTemplate.opsForHash().putAll(tokenKey,map); redisTemplate.opsForHash().putAll(tokenKey,map);
redisTemplate.expire(tokenKey,1, TimeUnit.DAYS);
return token; return token;
} }
public WsToken getToken(String token){
String tokenKey = String.format(RedisConstant.WS_TOKEN, token);
Map<Object, Object> entries = redisTemplate.opsForHash().entries(tokenKey);
if(entries.isEmpty()){
return null;
}
WsToken wsToken = new WsToken();
wsToken.setRoomId(MapGetUtil.getLong(entries.get("roomId")));
wsToken.setFromUid(MapGetUtil.getLong(entries.get("fromUid")));
wsToken.setToUid(MapGetUtil.getLong(entries.get("toUid")));
wsToken.setUserId(MapGetUtil.getLong(entries.get("userId")));
return wsToken;
}
public CallResp call(CallReq callReq){ public CallResp call(CallReq callReq){
Long userId = LoginHelper.getUserId(); Long userId = LoginHelper.getUserId();
User fromUser = userService.getById(userId); User fromUser = userService.getById(userId);

View File

@@ -13,11 +13,11 @@ public class RoomData {
private BigDecimal videoDivide; private BigDecimal videoDivide;
private Long payCoin = 0L; private Long payCoin = 0L;
private Long payIncome = 0L; private Long payIncome = 0L;
private Long hangUpTime; private Long hangUpTime; // 掉线时间
private Long settleTime; private Long settleTime; // 结算时间
private Long beginTime; private Long beginTime; // 开始时间
private boolean releaseRes = false; private boolean releaseRes = false;
} }

View File

@@ -12,4 +12,5 @@ public class UserData {
private String nickname; private String nickname;
private String userCode; private String userCode;
private Long connectTime; private Long connectTime;
private Long heartTime;
} }

View File

@@ -11,6 +11,13 @@ import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* key sessionKey
* value 当前用户信息
* 一个call 有两个redis
* <p>created on 2024/1/11 22:44</p>
* @author duet
*/
@Component @Component
public class FdCtxDataCache { public class FdCtxDataCache {
@Autowired @Autowired

View File

@@ -12,6 +12,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
* key : 房间号
* value { sessionKey 用户类型 }
* <p>created on 2024/1/11 22:45</p>
* @author duet
*/
@Component @Component
public class RoomCtxCache { public class RoomCtxCache {
@Autowired @Autowired
@@ -23,7 +29,7 @@ public class RoomCtxCache {
public void addFd(String sessionKey,Long roomId,Integer userType){ public void addFd(String sessionKey,Long roomId,Integer userType){
String key = getKey(roomId); String key = getKey(roomId);
redisTemplate.opsForHash().putIfAbsent(key,sessionKey,userType); redisTemplate.opsForHash().put(key,sessionKey,userType);
redisTemplate.expire(key,7, TimeUnit.DAYS); redisTemplate.expire(key,7, TimeUnit.DAYS);
} }

View File

@@ -20,6 +20,12 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
/**
* 房间信息
* 在拨打电话的时候就已经提前初始化
* <p>created on 2024/1/11 22:49</p>
* @author duet
*/
@Component @Component
public class RoomDataCache { public class RoomDataCache {
@Autowired @Autowired

View File

@@ -10,6 +10,11 @@ import org.springframework.stereotype.Component;
import java.util.Map; import java.util.Map;
/**
* 房间的用户信息 拨打电话前就已经创建好
* <p>created on 2024/1/11 22:50</p>
* @author duet
*/
@Component @Component
public class UserDataCache { public class UserDataCache {
@Autowired @Autowired

View File

@@ -28,11 +28,9 @@ public class WebSocketConfig {
if (StrUtil.isBlank(webSocketProperties.getPath())) { if (StrUtil.isBlank(webSocketProperties.getPath())) {
webSocketProperties.setPath("/ws"); webSocketProperties.setPath("/ws");
} }
if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) { if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) {
webSocketProperties.setAllowedOrigins("*"); webSocketProperties.setAllowedOrigins("*");
} }
return registry -> registry return registry -> registry
.addHandler(webSocketHandler, webSocketProperties.getPath()) .addHandler(webSocketHandler, webSocketProperties.getPath())
.addInterceptors(handshakeInterceptor) .addInterceptors(handshakeInterceptor)

View File

@@ -7,4 +7,13 @@ public class WsToken {
private Long roomId; private Long roomId;
private Long fromUid; private Long fromUid;
private Long toUid; private Long toUid;
private Long userId;
public boolean isCall(){
return userId.equals(fromUid);
}
public boolean isReceive(){
return userId.equals(toUid);
}
} }

View File

@@ -1,15 +1,18 @@
package com.ruoyi.cai.ws.handler; package com.ruoyi.cai.ws.handler;
import com.ruoyi.cai.chat.ChatManager;
import com.ruoyi.cai.ws.constant.WebSocketConstants; import com.ruoyi.cai.ws.constant.WebSocketConstants;
import com.ruoyi.cai.ws.holder.WebSocketSessionHolder; import com.ruoyi.cai.ws.holder.WebSocketSessionHolder;
import com.ruoyi.cai.ws.processon.OpenLogic; import com.ruoyi.cai.ws.processon.OpenLogic;
import com.ruoyi.cai.ws.util.WebSocketUtils; import com.ruoyi.cai.ws.util.WebSocketUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.*; import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler; import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import javax.websocket.server.PathParam;
import java.util.Map; import java.util.Map;
/** /**
@@ -29,13 +32,9 @@ public class RoomWebSocketHandler extends AbstractWebSocketHandler {
* 连接成功后 * 连接成功后
*/ */
@Override @Override
public void afterConnectionEstablished(WebSocketSession session) { public void afterConnectionEstablished(@NotNull WebSocketSession session) {
Map<String, Object> attributes = session.getAttributes();
if(attributes.get("token") != null){
WebSocketSessionHolder.addSession(attributes.get("token").toString(), session);
}
openLogic.processOn(session); openLogic.processOn(session);
log.info("[connect] sessionId: {},userId:{}", session.getId(), session.getId()); // log.info("[connect] sessionId: {},userId:{}", session.getId(), session.getId());
} }
/** /**

View File

@@ -3,7 +3,9 @@ package com.ruoyi.cai.ws.handler.message;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.cai.domain.Account; import com.ruoyi.cai.domain.Account;
import com.ruoyi.cai.domain.Gift; import com.ruoyi.cai.domain.Gift;
import com.ruoyi.cai.dto.ConsumeResp;
import com.ruoyi.cai.dto.app.query.GiveGiftRes; import com.ruoyi.cai.dto.app.query.GiveGiftRes;
import com.ruoyi.cai.manager.ConsumerManager;
import com.ruoyi.cai.service.AccountService; import com.ruoyi.cai.service.AccountService;
import com.ruoyi.cai.service.GiftService; import com.ruoyi.cai.service.GiftService;
import com.ruoyi.cai.service.UserGiftService; import com.ruoyi.cai.service.UserGiftService;
@@ -23,6 +25,8 @@ public class GiftMessageHandler extends AbstractMessageHandle implements IMessag
private AccountService accountService; private AccountService accountService;
@Autowired @Autowired
private UserGiftService userGiftService; private UserGiftService userGiftService;
@Autowired
private ConsumerManager consumerManager;
@Override @Override
public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) { public void processOn(Room room, FdCtxData fdCtxData, JSONObject map) {
Long giftId = map.getLong("giftId"); Long giftId = map.getLong("giftId");
@@ -50,8 +54,8 @@ public class GiftMessageHandler extends AbstractMessageHandle implements IMessag
giveGiftRes.setToUserId(fdCtxData.getTarUserId()); giveGiftRes.setToUserId(fdCtxData.getTarUserId());
giveGiftRes.setGiftId(giftId); giveGiftRes.setGiftId(giftId);
giveGiftRes.setGiftCount(giftCount); giveGiftRes.setGiftCount(giftCount);
boolean b = userGiftService.giveGift(giveGiftRes); ConsumeResp consumeResp = consumerManager.sendGift(giveGiftRes);
if(!b){ if(!consumeResp.isSuccess()){
sendToCurrent(fdCtxData,WsRMsgGen.sysNotice("赠送失败,请重试")); sendToCurrent(fdCtxData,WsRMsgGen.sysNotice("赠送失败,请重试"));
return; return;
} }

View File

@@ -97,8 +97,6 @@ public class WebSocketManager {
// 检查女神在线状态 TODO // 检查女神在线状态 TODO
// 关闭发起的其他房间 // 关闭发起的其他房间
roomService.closeAllRoom(call.getFromUid()); roomService.closeAllRoom(call.getFromUid());
// 删除旧房间记录 // 删除旧房间记录
roomService.delCallRoom(call.getFromUid()); roomService.delCallRoom(call.getFromUid());

View File

@@ -1,10 +1,11 @@
package com.ruoyi.cai.ws.processon; package com.ruoyi.cai.ws.processon;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.ruoyi.cai.trd.Agora; import com.ruoyi.cai.chat.ChatManager;
import com.ruoyi.cai.executor.ExecutorConstant; import com.ruoyi.cai.executor.ExecutorConstant;
import com.ruoyi.cai.service.AnchorService; import com.ruoyi.cai.service.AnchorService;
import com.ruoyi.cai.service.UserService; import com.ruoyi.cai.service.UserService;
import com.ruoyi.cai.trd.Agora;
import com.ruoyi.cai.ws.bean.FdCtxData; import com.ruoyi.cai.ws.bean.FdCtxData;
import com.ruoyi.cai.ws.bean.Room; import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.cache.*; import com.ruoyi.cai.ws.cache.*;
@@ -12,16 +13,21 @@ import com.ruoyi.cai.ws.constant.HangUpEnums;
import com.ruoyi.cai.ws.constant.RoomStatusEnums; import com.ruoyi.cai.ws.constant.RoomStatusEnums;
import com.ruoyi.cai.ws.constant.UserDataConstant; import com.ruoyi.cai.ws.constant.UserDataConstant;
import com.ruoyi.cai.ws.dto.WsRMsgGen; import com.ruoyi.cai.ws.dto.WsRMsgGen;
import com.ruoyi.cai.ws.dto.WsToken;
import com.ruoyi.cai.ws.holder.WebSocketSessionHolder;
import com.ruoyi.cai.ws.service.CheckConnectionDTO; import com.ruoyi.cai.ws.service.CheckConnectionDTO;
import com.ruoyi.cai.ws.service.RoomService; import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.cai.ws.util.MapGetUtil;
import com.ruoyi.cai.ws.util.RoomWebSocketUtil; import com.ruoyi.cai.ws.util.RoomWebSocketUtil;
import com.ruoyi.cai.ws.util.TimeConverter;
import com.ruoyi.cai.ws.util.WsExceptionUtil; import com.ruoyi.cai.ws.util.WsExceptionUtil;
import com.ruoyi.yunxin.Yunxin;
import com.ruoyi.yunxin.data.SendAttachMsgData;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -46,37 +52,39 @@ public class OpenLogic {
private AnchorService anchorService; private AnchorService anchorService;
@Autowired @Autowired
private Agora agora; private Agora agora;
@Autowired
private ChatManager chatManager;
@Autowired
private Yunxin yunxin;
public void processOn(WebSocketSession session) { public void processOn(WebSocketSession session) throws IOException {
Map<String, Object> map = session.getAttributes(); Map<String, Object> attributes = session.getAttributes();
String token = MapGetUtil.getString(map.get("token")); Object token = attributes.get("token");
Long roomId = MapGetUtil.getLong(map.get("roomId")); if(token == null){
Long userId = MapGetUtil.getLong(map.get("userId")); WsExceptionUtil.throwExceptionFast(session,"参数异常");
// 校验token return;
process(token,roomId,userId);
} }
WsToken wsToken = chatManager.getToken(String.valueOf(token));
public void process(String sessionKey,Long roomId,Long userId){ if(wsToken == null){
WsExceptionUtil.throwExceptionFast(session,"无效token");
return;
}
WebSocketSessionHolder.addSession(session.getId(), session);
Long roomId = wsToken.getRoomId();
Long userId = wsToken.getUserId();
Room room = roomService.load(roomId); Room room = roomService.load(roomId);
if(room == null || (room.getCallUserData().getId().equals(userId) && room.getReceiverUserData().getId().equals(userId))){ if(room == null || (room.getCallUserData().getId().equals(userId) && room.getReceiverUserData().getId().equals(userId))){
WsExceptionUtil.throwException(sessionKey,"房间不可用", HangUpEnums.OTHER,roomId); WsExceptionUtil.throwException(session,"房间不可用", HangUpEnums.OTHER,roomId);
return; return;
} }
CheckConnectionDTO checkConnect = roomService.checkConnect(room); CheckConnectionDTO checkConnect = roomService.checkConnect(room);
if(checkConnect != null){ if(checkConnect != null){
WsExceptionUtil.throwException(sessionKey,checkConnect.getMessage(),checkConnect.getHangUpEnums(),roomId); WsExceptionUtil.throwException(session,checkConnect.getMessage(),checkConnect.getHangUpEnums(),roomId);
return; return;
} }
if(userId.equals(room.getCallUserData().getId())){
// 走主叫方逻辑
callerConnection(sessionKey,room,userId);
}else {
// 走接收方逻辑
receiverConnection(sessionKey,room,userId);
}
// 保存上下文到redis // 保存上下文到redis
FdCtxData fdCtxData = new FdCtxData(); FdCtxData fdCtxData = new FdCtxData();
fdCtxData.setSessionKey(sessionKey); fdCtxData.setSessionKey(session.getId());
fdCtxData.setRoomId(room.getRoomId()); fdCtxData.setRoomId(room.getRoomId());
fdCtxData.setUserId(userId); fdCtxData.setUserId(userId);
if(userId.equals(room.getCallUserData().getId())){ if(userId.equals(room.getCallUserData().getId())){
@@ -89,10 +97,18 @@ public class OpenLogic {
fdCtxData.setTarUserType(UserDataConstant.TYPE_CALLER); fdCtxData.setTarUserType(UserDataConstant.TYPE_CALLER);
} }
fdCtxDataCache.save(fdCtxData); fdCtxDataCache.save(fdCtxData);
roomCtxCache.addFd(sessionKey,roomId,fdCtxData.getUserType()); roomCtxCache.addFd(session.getId(),roomId,fdCtxData.getUserType());
if(userId.equals(room.getCallUserData().getId())){
// 走主叫方逻辑
callerConnection(session,room,userId);
}else {
// 走接收方逻辑
receiverConnection(session,room,userId);
} }
public void callerConnection(String sessionKey,Room room,Long userId){ }
public void callerConnection(WebSocketSession session,Room room,Long userId){
boolean isFirst = false; boolean isFirst = false;
Integer status = room.getStatus(); Integer status = room.getStatus();
// 首次链接 // 首次链接
@@ -110,17 +126,18 @@ public class OpenLogic {
// 已经接通 // 已经接通
if(room.isOnline()){ if(room.isOnline()){
ExecutorConstant.ROOM_EXECUTOR.execute(() -> { ExecutorConstant.ROOM_EXECUTOR.execute(() -> {
// 已经接通,看一下是否掉线了,为重连
// 如果视频也掉线了,则重连的时候发送消息提示 // 如果视频也掉线了,则重连的时候发送消息提示
List<String> channelUsers = agora.getChannelUsers(room.getRoomId()); List<String> channelUsers = agora.getChannelUsers(room.getRoomId());
if(channelUsers.contains(userId+"")){ if(channelUsers.contains(userId+"")){
return; return;
} }
Long callTime = roomService.getCallTime(room); Long callTime = roomService.getCallTime(room);
RoomWebSocketUtil.sendSendMessage(sessionKey, WsRMsgGen.startVideo(room.getRoomId(), callTime)); RoomWebSocketUtil.sendSendMessage(session, WsRMsgGen.startVideo(room.getRoomId(), callTime));
RoomWebSocketUtil.sendSendMessage(sessionKey,WsRMsgGen.sysNotice("重连成功,房间已通话(转换成时分秒) ")); RoomWebSocketUtil.sendSendMessage(session,WsRMsgGen.sysNotice("重连成功,房间已通话 "+ TimeConverter.convertSecondsToHMS(callTime)));
String sessionKeyReceiver = roomCtxCache.getSessionKeyReceiverByRoomId(room.getRoomId()); String sessionKeyReceiver = roomCtxCache.getSessionKeyReceiverByRoomId(room.getRoomId());
if(StringUtils.isNotEmpty(sessionKeyReceiver)){ if(StringUtils.isNotEmpty(sessionKeyReceiver)){
RoomWebSocketUtil.sendSendMessage(sessionKey,WsRMsgGen.sysNotice("对方已重连成功")); RoomWebSocketUtil.sendSendMessage(session,WsRMsgGen.sysNotice("对方已重连成功"));
} }
}); });
} }
@@ -128,13 +145,19 @@ public class OpenLogic {
RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(status) || RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(status) ||
RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(status)){ RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(status)){
// 给当前会话发送消息 - 连线成功 // 给当前会话发送消息 - 连线成功
RoomWebSocketUtil.sendSendMessage(sessionKey, WsRMsgGen.response(room.getRoomId())); RoomWebSocketUtil.sendSendMessage(session, WsRMsgGen.response(room.getRoomId()));
} }
if(isFirst){ if(isFirst){
// 给对方发送呼叫页面 TODO ExecutorConstant.ROOM_EXECUTOR.execute(() -> {
// 给对方发送呼叫页面
;
SendAttachMsgData msg = SendAttachMsgData.init(room.getRoomId());
yunxin.sendAttachMsg(room.getCallUserData().getId(),
room.getReceiverUserData().getId(), msg);
});
} }
} }
public void receiverConnection(String sessionKey,Room room,Long userId){ public void receiverConnection(WebSocketSession session,Room room,Long userId){
Integer status = room.getStatus(); Integer status = room.getStatus();
// 首次链接 // 首次链接
if(RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(status)){ if(RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(status)){
@@ -143,6 +166,7 @@ public class OpenLogic {
map.put("connectTime", DateUtil.currentSeconds()); map.put("connectTime", DateUtil.currentSeconds());
map.put("heartTime",DateUtil.currentSeconds()); map.put("heartTime",DateUtil.currentSeconds());
userDataCache.hMSet(room.getRoomId(), UserDataConstant.TYPE_RECEIVER,map); userDataCache.hMSet(room.getRoomId(), UserDataConstant.TYPE_RECEIVER,map);
// 房间号状态设置为 接收方已连接
boolean res = roomDataCache.setStatusReceiverConnection(room.getRoomId()); boolean res = roomDataCache.setStatusReceiverConnection(room.getRoomId());
if(!res){ if(!res){
return; return;
@@ -150,8 +174,8 @@ public class OpenLogic {
userService.updateVideoStatus(userId,1); userService.updateVideoStatus(userId,1);
anchorService.updateVideoStatus(userId,1); anchorService.updateVideoStatus(userId,1);
} }
RoomWebSocketUtil.sendSendMessage(sessionKey, WsRMsgGen.response(room.getRoomId())); RoomWebSocketUtil.sendSendMessage(session, WsRMsgGen.response(room.getRoomId()));
RoomWebSocketUtil.sendSendMessage(sessionKey, WsRMsgGen.updateTip()); RoomWebSocketUtil.sendSendMessage(session, WsRMsgGen.updateTip());
} }

View File

@@ -2,6 +2,7 @@ package com.ruoyi.cai.ws.util;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.ruoyi.cai.ws.dto.WsR; import com.ruoyi.cai.ws.dto.WsR;
import org.springframework.web.socket.WebSocketSession;
import java.util.List; import java.util.List;
@@ -10,6 +11,10 @@ public class RoomWebSocketUtil {
WebSocketUtils.sendMessage(sessionKey, JSON.toJSONString(r)); WebSocketUtils.sendMessage(sessionKey, JSON.toJSONString(r));
} }
public static void sendSendMessage(WebSocketSession sessionKey, WsR r){
WebSocketUtils.sendMessage(sessionKey, JSON.toJSONString(r));
}
public static void sendSendMessage(List<String> sessionKey, WsR r){ public static void sendSendMessage(List<String> sessionKey, WsR r){
for (String s : sessionKey) { for (String s : sessionKey) {
WebSocketUtils.sendMessage(s, JSON.toJSONString(r)); WebSocketUtils.sendMessage(s, JSON.toJSONString(r));

View File

@@ -0,0 +1,10 @@
package com.ruoyi.cai.ws.util;
public class TimeConverter {
public static String convertSecondsToHMS(Long seconds){
long hours = seconds / 3600;
long minutes = (seconds % 3600) / 60;
long secondsShow = seconds % 60;
return hours + ":" + minutes + ":" + secondsShow;
}
}

View File

@@ -33,12 +33,16 @@ public class WebSocketUtils {
public static boolean close(String sessionKey) { public static boolean close(String sessionKey) {
WebSocketSession sessions = WebSocketSessionHolder.getSessions(sessionKey); WebSocketSession sessions = WebSocketSessionHolder.getSessions(sessionKey);
if(sessions != null){ return close(sessions);
}
public static boolean close(WebSocketSession session) {
if(session != null){
try { try {
sessions.close(); session.close();
return true; return true;
} catch (IOException e) { } catch (IOException e) {
log.error("关闭ws失败sessionKey={}",sessionKey,e); log.error("关闭ws失败session={}",session,e);
} }
} }
return false; return false;

View File

@@ -3,6 +3,9 @@ package com.ruoyi.cai.ws.util;
import com.ruoyi.cai.ws.constant.HangUpEnums; import com.ruoyi.cai.ws.constant.HangUpEnums;
import com.ruoyi.cai.ws.dto.WsRMsgGen; import com.ruoyi.cai.ws.dto.WsRMsgGen;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
@Slf4j @Slf4j
public class WsExceptionUtil { public class WsExceptionUtil {
@@ -15,6 +18,25 @@ public class WsExceptionUtil {
if(!close){ if(!close){
log.warn("ws连接时发现异常{}sessionKey {} roomid {}", message, sessionKey, roomId); log.warn("ws连接时发现异常{}sessionKey {} roomid {}", message, sessionKey, roomId);
} }
}
public static void throwException(WebSocketSession sessionKey, String message, HangUpEnums hangUpType, Long roomId){
if(hangUpType == null){
hangUpType = HangUpEnums.OTHER;
}
RoomWebSocketUtil.sendSendMessage(sessionKey, WsRMsgGen.hangup(message,roomId,hangUpType.getCode()));
boolean close = WebSocketUtils.close(sessionKey);
if(!close){
log.warn("ws连接时发现异常{}sessionKey {} roomid {}", message, sessionKey, roomId);
}
}
public static void throwExceptionFast(WebSocketSession session,String message){
RoomWebSocketUtil.sendSendMessage(session, WsRMsgGen.hangup(message, null, HangUpEnums.OTHER.getCode()));
try {
session.close();
} catch (IOException e) {
log.error("快速关闭ws 失败",e);
}
} }
} }

View File

@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON;
import com.ruoyi.yunxin.client.ImMessageClient; import com.ruoyi.yunxin.client.ImMessageClient;
import com.ruoyi.yunxin.config.YunxinProperties; import com.ruoyi.yunxin.config.YunxinProperties;
import com.ruoyi.yunxin.req.Option; import com.ruoyi.yunxin.req.Option;
import com.ruoyi.yunxin.req.SendAttachMsgReq;
import com.ruoyi.yunxin.req.SendBatchMsgReq; import com.ruoyi.yunxin.req.SendBatchMsgReq;
import com.ruoyi.yunxin.req.SendMsgReq; import com.ruoyi.yunxin.req.SendMsgReq;
import com.ruoyi.yunxin.req.type.YxTextData; import com.ruoyi.yunxin.req.type.YxTextData;
@@ -25,7 +26,6 @@ public class Yunxin {
@Resource @Resource
private ImMessageClient messageClient; private ImMessageClient messageClient;
@Deprecated
public YxDataR<SendMsgResp> sendTo(Long toUid,Long fromUid,Object data){ public YxDataR<SendMsgResp> sendTo(Long toUid,Long fromUid,Object data){
SendMsgReq req = new SendMsgReq(); SendMsgReq req = new SendMsgReq();
req.setFrom(fromUid == null ? yunxinProperties.getDefaultFromUid() : fromUid+""); req.setFrom(fromUid == null ? yunxinProperties.getDefaultFromUid() : fromUid+"");
@@ -44,4 +44,13 @@ public class Yunxin {
return messageClient.sendBatchMsg(req); return messageClient.sendBatchMsg(req);
} }
public YxDataR<YxCommonR> sendAttachMsg(Long fromUid, Long toUid, Object data){
SendAttachMsgReq sendAttachMsgReq = new SendAttachMsgReq();
sendAttachMsgReq.setFrom(fromUid+"");
sendAttachMsgReq.setTo(toUid+"");
sendAttachMsgReq.setAttach(JSON.toJSONString(data));
sendAttachMsgReq.setOption(JSON.toJSONString(new Option()));
return messageClient.sendAttachMsg(sendAttachMsgReq);
}
} }

View File

@@ -1,8 +1,10 @@
package com.ruoyi.yunxin.client; package com.ruoyi.yunxin.client;
import com.dtflys.forest.annotation.BaseRequest; import com.dtflys.forest.annotation.BaseRequest;
import com.dtflys.forest.annotation.Body;
import com.dtflys.forest.annotation.Post; import com.dtflys.forest.annotation.Post;
import com.ruoyi.yunxin.interceptor.GlodonTokenInterceptor; import com.ruoyi.yunxin.interceptor.GlodonTokenInterceptor;
import com.ruoyi.yunxin.req.SendAttachMsgReq;
import com.ruoyi.yunxin.req.SendBatchMsgReq; import com.ruoyi.yunxin.req.SendBatchMsgReq;
import com.ruoyi.yunxin.req.SendMsgReq; import com.ruoyi.yunxin.req.SendMsgReq;
import com.ruoyi.yunxin.resp.SendMsgResp; import com.ruoyi.yunxin.resp.SendMsgResp;
@@ -12,14 +14,24 @@ import com.ruoyi.yunxin.resp.YxDataR;
@BaseRequest(baseURL = "${baseUrl}", interceptor = GlodonTokenInterceptor.class) @BaseRequest(baseURL = "${baseUrl}", interceptor = GlodonTokenInterceptor.class)
public interface ImMessageClient { public interface ImMessageClient {
/**
* 发送自定义消息
* @param req
* @return
*/
@Post(url = "/nimserver/msg/sendMsg.action") @Post(url = "/nimserver/msg/sendMsg.action")
YxDataR<SendMsgResp> sendMsg(SendMsgReq req); YxDataR<SendMsgResp> sendMsg(@Body SendMsgReq req);
@Post(url = "/nimserver/msg/sendBatchMsg.action") @Post(url = "/nimserver/msg/sendBatchMsg.action")
YxDataR<YxCommonR> sendBatchMsg(SendBatchMsgReq req); YxDataR<YxCommonR> sendBatchMsg(@Body SendBatchMsgReq req);
// @Post(url = "/nimserver/msg/sendAttachMsg.action") /**
// YxR<SendMsgResp> sendAttachMsg(SendMsgReq req); * 发送自定义系统消息
* @param req
* @return
*/
@Post(url = "/nimserver/msg/sendAttachMsg.action")
YxDataR<YxCommonR> sendAttachMsg(@Body SendAttachMsgReq req);
} }

View File

@@ -0,0 +1,33 @@
package com.ruoyi.yunxin.data;
import cn.hutool.core.date.DateUtil;
import lombok.Data;
/**
* 系统消息通知
*/
@Data
public class SendAttachMsgData {
private Long id = 11L;
private SendAttachMsgDataMsg data;
@Data
public static class SendAttachMsgDataMsg {
private Long amount;
private Long callTime = DateUtil.currentSeconds();
private Long giftTotal = 0L;
private Long id = 0L;
private Integer linkType = 0;
private Long time = 0L;
private Long toid = 0L;
private Long roomId;
}
public static SendAttachMsgData init(Long roomId){
SendAttachMsgData data = new SendAttachMsgData();
SendAttachMsgDataMsg msgDataMsg = new SendAttachMsgDataMsg();
msgDataMsg.setRoomId(roomId);
data.setData(msgDataMsg);
return data;
}
}

View File

@@ -4,5 +4,9 @@ import lombok.Data;
@Data @Data
public class SendAttachMsgReq { public class SendAttachMsgReq {
private String from;
private Integer msgType = 0;
private String to;
private String attach;
private String option;
} }