committed by
Gitee
561 changed files with 43937 additions and 2075 deletions
@ -1,10 +1,10 @@ |
|||
package com.bx.imclient.listener; |
|||
|
|||
|
|||
import com.bx.imcommon.model.SendResult; |
|||
import com.bx.imcommon.model.IMSendResult; |
|||
|
|||
public interface MessageListener { |
|||
public interface MessageListener<T> { |
|||
|
|||
void process(SendResult result); |
|||
void process(IMSendResult<T> result); |
|||
|
|||
} |
|||
|
|||
@ -1,19 +1,18 @@ |
|||
package com.bx.imcommon.contant; |
|||
|
|||
public class RedisKey { |
|||
public class IMRedisKey { |
|||
|
|||
// im-server最大id,从0开始递增
|
|||
public final static String IM_MAX_SERVER_ID = "im:max_server_id"; |
|||
// 用户ID所连接的IM-server的ID
|
|||
public final static String IM_USER_SERVER_ID = "im:user:server_id:"; |
|||
public final static String IM_USER_SERVER_ID = "im:user:server_id"; |
|||
// 未读私聊消息队列
|
|||
public final static String IM_UNREAD_PRIVATE_QUEUE = "im:unread:private:"; |
|||
public final static String IM_UNREAD_PRIVATE_QUEUE = "im:unread:private"; |
|||
// 未读群聊消息队列
|
|||
public final static String IM_UNREAD_GROUP_QUEUE = "im:unread:group:"; |
|||
public final static String IM_UNREAD_GROUP_QUEUE = "im:unread:group"; |
|||
// 私聊消息发送结果队列
|
|||
public final static String IM_RESULT_PRIVATE_QUEUE = "im:result:private"; |
|||
// 群聊消息发送结果队列
|
|||
public final static String IM_RESULT_GROUP_QUEUE = "im:result:group"; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
package com.bx.imcommon.enums; |
|||
|
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public enum IMTerminalType { |
|||
|
|||
WEB(0,"web"), |
|||
APP(1,"app"); |
|||
|
|||
private Integer code; |
|||
|
|||
private String desc; |
|||
|
|||
IMTerminalType(Integer index, String desc) { |
|||
this.code =index; |
|||
this.desc=desc; |
|||
} |
|||
|
|||
public static IMTerminalType fromCode(Integer code){ |
|||
for (IMTerminalType typeEnum:values()) { |
|||
if (typeEnum.code.equals(code)) { |
|||
return typeEnum; |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
public static List<Integer> codes(){ |
|||
return Arrays.stream(values()).map(IMTerminalType::code).collect(Collectors.toList()); |
|||
} |
|||
|
|||
public String description() { |
|||
return desc; |
|||
} |
|||
|
|||
public Integer code(){ |
|||
return this.code; |
|||
} |
|||
|
|||
} |
|||
@ -1,42 +0,0 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import com.bx.imcommon.serializer.DateToLongSerializer; |
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import lombok.Data; |
|||
|
|||
import java.util.Date; |
|||
|
|||
@Data |
|||
public class GroupMessageInfo { |
|||
|
|||
/* |
|||
* 消息id |
|||
*/ |
|||
private Long id; |
|||
|
|||
/* |
|||
* 群聊id |
|||
*/ |
|||
private Long groupId; |
|||
|
|||
/* |
|||
* 发送者id |
|||
*/ |
|||
private Long sendId; |
|||
|
|||
/* |
|||
* 消息内容 |
|||
*/ |
|||
private String content; |
|||
|
|||
/* |
|||
* 消息内容类型 具体枚举值由应用层定义 |
|||
*/ |
|||
private Integer type; |
|||
|
|||
/** |
|||
* 发送时间 |
|||
*/ |
|||
@JsonSerialize(using = DateToLongSerializer.class) |
|||
private Date sendTime; |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import com.bx.imcommon.enums.IMTerminalType; |
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class IMGroupMessage<T> { |
|||
|
|||
/** |
|||
* 发送方 |
|||
*/ |
|||
private IMUserInfo sender; |
|||
|
|||
/** |
|||
* 接收者id列表(群成员列表) |
|||
*/ |
|||
private List<Long> recvIds; |
|||
|
|||
|
|||
/** |
|||
* 接收者终端类型,默认全部 |
|||
*/ |
|||
private List<Integer> recvTerminals = IMTerminalType.codes(); |
|||
|
|||
/** |
|||
* 是否发送给自己的其他终端,默认true |
|||
*/ |
|||
private Boolean sendToSelf = true; |
|||
|
|||
/** |
|||
* 是否需要回推发送结果,默认true |
|||
*/ |
|||
private Boolean sendResult = true; |
|||
|
|||
/** |
|||
* 消息内容 |
|||
*/ |
|||
private T data; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import com.bx.imcommon.enums.IMTerminalType; |
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
|
|||
@Data |
|||
public class IMPrivateMessage<T> { |
|||
|
|||
/** |
|||
* 发送方 |
|||
*/ |
|||
private IMUserInfo sender; |
|||
|
|||
/** |
|||
* 接收者id |
|||
*/ |
|||
private Long recvId; |
|||
|
|||
|
|||
/** |
|||
* 接收者终端类型,默认全部 |
|||
*/ |
|||
private List<Integer> recvTerminals = IMTerminalType.codes(); |
|||
|
|||
/** |
|||
* 是否发送给自己的其他终端,默认true |
|||
*/ |
|||
private Boolean sendToSelf = true; |
|||
|
|||
/** |
|||
* 是否需要回推发送结果,默认true |
|||
*/ |
|||
private Boolean sendResult = true; |
|||
|
|||
/** |
|||
* 消息内容 |
|||
*/ |
|||
private T data; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class IMSendResult<T> { |
|||
|
|||
/** |
|||
* 发送方 |
|||
*/ |
|||
private IMUserInfo sender; |
|||
|
|||
/** |
|||
* 接收方 |
|||
*/ |
|||
private IMUserInfo receiver; |
|||
|
|||
/* |
|||
* 发送状态 IMCmdType |
|||
*/ |
|||
private Integer code; |
|||
|
|||
/* |
|||
* 消息内容 |
|||
*/ |
|||
private T data; |
|||
|
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import com.bx.imcommon.enums.IMTerminalType; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class IMSessionInfo { |
|||
/* |
|||
* 用户id |
|||
*/ |
|||
private Long userId; |
|||
|
|||
/* |
|||
* 终端类型 |
|||
*/ |
|||
private Integer terminal; |
|||
|
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Data; |
|||
import lombok.NoArgsConstructor; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author: 谢绍许 |
|||
* @date: 2023-09-24 09:23:11 |
|||
* @version: 1.0 |
|||
*/ |
|||
@Data |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
public class IMUserInfo { |
|||
|
|||
/** |
|||
* 用户id |
|||
*/ |
|||
private Long id; |
|||
|
|||
/** |
|||
* 用户终端类型 IMTerminalType |
|||
*/ |
|||
private Integer terminal; |
|||
|
|||
|
|||
} |
|||
@ -1,42 +0,0 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import com.bx.imcommon.serializer.DateToLongSerializer; |
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import lombok.Data; |
|||
|
|||
import java.util.Date; |
|||
|
|||
@Data |
|||
public class PrivateMessageInfo { |
|||
|
|||
/* |
|||
* 消息id |
|||
*/ |
|||
private long id; |
|||
|
|||
/* |
|||
* 发送者id |
|||
*/ |
|||
private Long sendId; |
|||
|
|||
/* |
|||
* 接收者id |
|||
*/ |
|||
private Long recvId; |
|||
|
|||
/* |
|||
* 发送内容 |
|||
*/ |
|||
private String content; |
|||
|
|||
/* |
|||
* 消息内容类型 具体枚举值由应用层定义 |
|||
*/ |
|||
private Integer type; |
|||
|
|||
/** |
|||
* 发送时间 |
|||
*/ |
|||
@JsonSerialize(using = DateToLongSerializer.class) |
|||
private Date sendTime; |
|||
} |
|||
@ -1,24 +0,0 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import com.bx.imcommon.enums.IMSendCode; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class SendResult<T> { |
|||
|
|||
/* |
|||
* 接收者id |
|||
*/ |
|||
private Long recvId; |
|||
|
|||
/* |
|||
* 发送状态 |
|||
*/ |
|||
private IMSendCode code; |
|||
|
|||
/* |
|||
* 消息体(透传) |
|||
*/ |
|||
private T messageInfo; |
|||
|
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
package com.bx.implatform.dto; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
import org.hibernate.validator.constraints.Length; |
|||
|
|||
import javax.validation.constraints.NotEmpty; |
|||
import javax.validation.constraints.NotNull; |
|||
|
|||
@Data |
|||
@ApiModel("群聊消息DTO") |
|||
public class GroupMessageDTO { |
|||
|
|||
@NotNull(message="群聊id不可为空") |
|||
@ApiModelProperty(value = "群聊id") |
|||
private Long groupId; |
|||
|
|||
|
|||
@Length(max=1024,message = "内容长度不得大于1024") |
|||
@NotEmpty(message="发送内容不可为空") |
|||
@ApiModelProperty(value = "发送内容") |
|||
private String content; |
|||
|
|||
@NotNull(message="消息类型不可为空") |
|||
@ApiModelProperty(value = "消息类型") |
|||
private Integer type; |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
package com.bx.implatform.dto; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
import javax.validation.constraints.NotEmpty; |
|||
|
|||
@Data |
|||
@ApiModel("修改密码DTO") |
|||
public class ModifyPwdDTO { |
|||
|
|||
@NotEmpty(message="旧用户密码不可为空") |
|||
@ApiModelProperty(value = "旧用户密码") |
|||
private String oldPassword; |
|||
|
|||
@NotEmpty(message="新用户密码不可为空") |
|||
@ApiModelProperty(value = "新用户密码") |
|||
private String newPassword; |
|||
|
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
package com.bx.implatform.dto; |
|||
|
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
import org.hibernate.validator.constraints.Length; |
|||
|
|||
import javax.validation.constraints.NotEmpty; |
|||
import javax.validation.constraints.NotNull; |
|||
|
|||
@Data |
|||
@ApiModel("私聊消息DTO") |
|||
public class PrivateMessageDTO { |
|||
|
|||
|
|||
@NotNull(message="接收用户id不可为空") |
|||
@ApiModelProperty(value = "接收用户id") |
|||
private Long recvId; |
|||
|
|||
|
|||
@Length(max=1024,message = "内容长度不得大于1024") |
|||
@NotEmpty(message="发送内容不可为空") |
|||
@ApiModelProperty(value = "发送内容") |
|||
private String content; |
|||
|
|||
@NotNull(message="消息类型不可为空") |
|||
@ApiModelProperty(value = "消息类型") |
|||
private Integer type; |
|||
|
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
package com.bx.implatform.service; |
|||
|
|||
import com.bx.implatform.config.ICEServer; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import java.util.List; |
|||
|
|||
|
|||
/** |
|||
* webrtc 通信服务 |
|||
* @author |
|||
*/ |
|||
public interface IWebrtcService { |
|||
|
|||
void call(Long uid, String offer); |
|||
|
|||
void accept( Long uid,@RequestBody String answer); |
|||
|
|||
void reject( Long uid); |
|||
|
|||
void cancel( Long uid); |
|||
|
|||
void failed( Long uid, String reason); |
|||
|
|||
void leave( Long uid) ; |
|||
|
|||
void candidate( Long uid, String candidate); |
|||
|
|||
List<ICEServer> getIceServers(); |
|||
|
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,245 @@ |
|||
package com.bx.implatform.service.impl; |
|||
|
|||
import com.bx.imclient.IMClient; |
|||
import com.bx.imcommon.model.IMPrivateMessage; |
|||
import com.bx.imcommon.model.IMUserInfo; |
|||
import com.bx.implatform.vo.PrivateMessageVO; |
|||
import com.bx.implatform.config.ICEServer; |
|||
import com.bx.implatform.config.ICEServerConfig; |
|||
import com.bx.implatform.contant.RedisKey; |
|||
import com.bx.implatform.enums.MessageType; |
|||
import com.bx.implatform.exception.GlobalException; |
|||
import com.bx.implatform.service.IWebrtcService; |
|||
import com.bx.implatform.session.SessionContext; |
|||
import com.bx.implatform.session.UserSession; |
|||
import com.bx.implatform.session.WebrtcSession; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
public class WebrtcServiceImpl implements IWebrtcService { |
|||
|
|||
@Autowired |
|||
private IMClient imClient; |
|||
@Autowired |
|||
private RedisTemplate<String, Object> redisTemplate; |
|||
@Autowired |
|||
private ICEServerConfig iceServerConfig; |
|||
|
|||
@Override |
|||
public void call(Long uid, String offer) { |
|||
UserSession session = SessionContext.getSession(); |
|||
if (!imClient.isOnline(uid)) { |
|||
throw new GlobalException("对方目前不在线"); |
|||
} |
|||
// 创建webrtc会话
|
|||
WebrtcSession webrtcSession = new WebrtcSession(); |
|||
webrtcSession.setCallerId(session.getUserId()); |
|||
webrtcSession.setCallerTerminal(session.getTerminal()); |
|||
String key = getSessionKey(session.getUserId(), uid); |
|||
redisTemplate.opsForValue().set(key, webrtcSession, 12, TimeUnit.HOURS); |
|||
// 向对方所有终端发起呼叫
|
|||
PrivateMessageVO messageInfo = new PrivateMessageVO(); |
|||
messageInfo.setType(MessageType.RTC_CALL.code()); |
|||
messageInfo.setRecvId(uid); |
|||
messageInfo.setSendId(session.getUserId()); |
|||
messageInfo.setContent(offer); |
|||
|
|||
IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>(); |
|||
sendMessage.setSender(new IMUserInfo(session.getUserId(),session.getTerminal())); |
|||
sendMessage.setRecvId(uid); |
|||
sendMessage.setSendToSelf(false); |
|||
sendMessage.setSendResult(false); |
|||
sendMessage.setData(messageInfo); |
|||
imClient.sendPrivateMessage(sendMessage); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void accept(Long uid, @RequestBody String answer) { |
|||
UserSession session = SessionContext.getSession(); |
|||
// 查询webrtc会话
|
|||
WebrtcSession webrtcSession = getWebrtcSession(session.getUserId(), uid); |
|||
// 更新接受者信息
|
|||
webrtcSession.setAcceptorId(session.getUserId()); |
|||
webrtcSession.setAcceptorTerminal(session.getTerminal()); |
|||
String key = getSessionKey(session.getUserId(), uid); |
|||
redisTemplate.opsForValue().set(key, webrtcSession, 12, TimeUnit.HOURS); |
|||
// 向发起人推送接受通话信令
|
|||
PrivateMessageVO messageInfo = new PrivateMessageVO(); |
|||
messageInfo.setType(MessageType.RTC_ACCEPT.code()); |
|||
messageInfo.setRecvId(uid); |
|||
messageInfo.setSendId(session.getUserId()); |
|||
messageInfo.setContent(answer); |
|||
|
|||
IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>(); |
|||
sendMessage.setSender(new IMUserInfo(session.getUserId(),session.getTerminal())); |
|||
sendMessage.setRecvId(uid); |
|||
// 告知其他终端已经接受会话,中止呼叫
|
|||
sendMessage.setSendToSelf(true); |
|||
sendMessage.setSendResult(false); |
|||
sendMessage.setRecvTerminals((Collections.singletonList(webrtcSession.getCallerTerminal()))); |
|||
sendMessage.setData(messageInfo); |
|||
imClient.sendPrivateMessage(sendMessage); |
|||
} |
|||
|
|||
@Override |
|||
public void reject(Long uid) { |
|||
UserSession session = SessionContext.getSession(); |
|||
// 查询webrtc会话
|
|||
WebrtcSession webrtcSession = getWebrtcSession(session.getUserId(), uid); |
|||
// 删除会话信息
|
|||
removeWebrtcSession(uid, session.getUserId()); |
|||
// 向发起人推送拒绝通话信令
|
|||
PrivateMessageVO messageInfo = new PrivateMessageVO(); |
|||
messageInfo.setType(MessageType.RTC_REJECT.code()); |
|||
messageInfo.setRecvId(uid); |
|||
messageInfo.setSendId(session.getUserId()); |
|||
|
|||
IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>(); |
|||
sendMessage.setSender(new IMUserInfo(session.getUserId(),session.getTerminal())); |
|||
sendMessage.setRecvId(uid); |
|||
// 告知其他终端已经拒绝会话,中止呼叫
|
|||
sendMessage.setSendToSelf(true); |
|||
sendMessage.setSendResult(false); |
|||
sendMessage.setRecvTerminals(Collections.singletonList(webrtcSession.getCallerTerminal())); |
|||
sendMessage.setData(messageInfo); |
|||
imClient.sendPrivateMessage(sendMessage); |
|||
} |
|||
|
|||
@Override |
|||
public void cancel(Long uid) { |
|||
UserSession session = SessionContext.getSession(); |
|||
// 删除会话信息
|
|||
removeWebrtcSession(session.getUserId(), uid); |
|||
// 向对方所有终端推送取消通话信令
|
|||
PrivateMessageVO messageInfo = new PrivateMessageVO(); |
|||
messageInfo.setType(MessageType.RTC_ACCEPT.code()); |
|||
messageInfo.setRecvId(uid); |
|||
messageInfo.setSendId(session.getUserId()); |
|||
|
|||
IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>(); |
|||
sendMessage.setSender(new IMUserInfo(session.getUserId(),session.getTerminal())); |
|||
sendMessage.setRecvId(uid); |
|||
sendMessage.setSendToSelf(false); |
|||
sendMessage.setSendResult(false); |
|||
sendMessage.setData(messageInfo); |
|||
// 通知对方取消会话
|
|||
imClient.sendPrivateMessage(sendMessage); |
|||
} |
|||
|
|||
@Override |
|||
public void failed(Long uid, String reason) { |
|||
UserSession session = SessionContext.getSession(); |
|||
// 查询webrtc会话
|
|||
WebrtcSession webrtcSession = getWebrtcSession(session.getUserId(), uid); |
|||
// 删除会话信息
|
|||
removeWebrtcSession(uid, session.getUserId()); |
|||
// 向发起方推送通话失败信令
|
|||
PrivateMessageVO messageInfo = new PrivateMessageVO(); |
|||
messageInfo.setType(MessageType.RTC_FAILED.code()); |
|||
messageInfo.setRecvId(uid); |
|||
messageInfo.setSendId(session.getUserId()); |
|||
|
|||
IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>(); |
|||
sendMessage.setSender(new IMUserInfo(session.getUserId(),session.getTerminal())); |
|||
sendMessage.setRecvId(uid); |
|||
// 告知其他终端已经会话失败,中止呼叫
|
|||
sendMessage.setSendToSelf(true); |
|||
sendMessage.setSendResult(false); |
|||
sendMessage.setRecvTerminals(Collections.singletonList(webrtcSession.getCallerTerminal())); |
|||
sendMessage.setData(messageInfo); |
|||
// 通知对方取消会话
|
|||
imClient.sendPrivateMessage(sendMessage); |
|||
|
|||
} |
|||
|
|||
@Override |
|||
public void leave(Long uid) { |
|||
UserSession session = SessionContext.getSession(); |
|||
// 查询webrtc会话
|
|||
WebrtcSession webrtcSession = getWebrtcSession(session.getUserId(), uid); |
|||
// 删除会话信息
|
|||
removeWebrtcSession(uid, session.getUserId()); |
|||
// 向对方推送挂断通话信令
|
|||
PrivateMessageVO messageInfo = new PrivateMessageVO(); |
|||
messageInfo.setType(MessageType.RTC_HANDUP.code()); |
|||
messageInfo.setRecvId(uid); |
|||
messageInfo.setSendId(session.getUserId()); |
|||
|
|||
IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>(); |
|||
sendMessage.setSender(new IMUserInfo(session.getUserId(),session.getTerminal())); |
|||
sendMessage.setRecvId(uid); |
|||
sendMessage.setSendToSelf(false); |
|||
sendMessage.setSendResult(false); |
|||
Integer terminal = getTerminalType(uid, webrtcSession); |
|||
sendMessage.setRecvTerminals(Collections.singletonList(terminal)); |
|||
sendMessage.setData(messageInfo); |
|||
// 通知对方取消会话
|
|||
imClient.sendPrivateMessage(sendMessage); |
|||
} |
|||
|
|||
@Override |
|||
public void candidate(Long uid, String candidate) { |
|||
UserSession session = SessionContext.getSession(); |
|||
// 查询webrtc会话
|
|||
WebrtcSession webrtcSession = getWebrtcSession(session.getUserId(), uid); |
|||
// 向发起方推送同步candidate信令
|
|||
PrivateMessageVO messageInfo = new PrivateMessageVO(); |
|||
messageInfo.setType(MessageType.RTC_CANDIDATE.code()); |
|||
messageInfo.setRecvId(uid); |
|||
messageInfo.setSendId(session.getUserId()); |
|||
messageInfo.setContent(candidate); |
|||
|
|||
IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>(); |
|||
sendMessage.setSender(new IMUserInfo(session.getUserId(),session.getTerminal())); |
|||
sendMessage.setRecvId(uid); |
|||
sendMessage.setSendToSelf(false); |
|||
sendMessage.setSendResult(false); |
|||
Integer terminal = getTerminalType(uid, webrtcSession); |
|||
sendMessage.setRecvTerminals(Collections.singletonList(terminal)); |
|||
sendMessage.setData(messageInfo); |
|||
imClient.sendPrivateMessage(sendMessage); |
|||
} |
|||
|
|||
@Override |
|||
public List<ICEServer> getIceServers() { |
|||
return iceServerConfig.getIceServers(); |
|||
} |
|||
|
|||
private WebrtcSession getWebrtcSession(Long userId, Long uid) { |
|||
String key = getSessionKey(userId, uid); |
|||
WebrtcSession webrtcSession = (WebrtcSession)redisTemplate.opsForValue().get(key); |
|||
if (webrtcSession == null) { |
|||
throw new GlobalException("视频通话已结束"); |
|||
} |
|||
return webrtcSession; |
|||
} |
|||
|
|||
private void removeWebrtcSession(Long userId, Long uid) { |
|||
String key = getSessionKey(userId, uid); |
|||
redisTemplate.delete(key); |
|||
} |
|||
|
|||
private String getSessionKey(Long id1, Long id2) { |
|||
Long minId = id1 > id2 ? id2 : id1; |
|||
Long maxId = id1 > id2 ? id1 : id2; |
|||
return String.join(":", RedisKey.IM_WEBRTC_SESSION, minId.toString(), maxId.toString()); |
|||
} |
|||
|
|||
private Integer getTerminalType(Long uid, WebrtcSession webrtcSession) { |
|||
if (uid.equals(webrtcSession.getCallerId())) { |
|||
return webrtcSession.getCallerTerminal(); |
|||
} |
|||
return webrtcSession.getAcceptorTerminal(); |
|||
} |
|||
|
|||
} |
|||
@ -1,11 +1,20 @@ |
|||
package com.bx.implatform.session; |
|||
|
|||
import com.bx.imcommon.model.IMSessionInfo; |
|||
import lombok.Data; |
|||
|
|||
|
|||
|
|||
@Data |
|||
public class UserSession { |
|||
public class UserSession extends IMSessionInfo { |
|||
|
|||
private Long id; |
|||
/* |
|||
* 用户名称 |
|||
*/ |
|||
private String userName; |
|||
|
|||
/* |
|||
* 用户昵称 |
|||
*/ |
|||
private String nickName; |
|||
} |
|||
|
|||
@ -0,0 +1,32 @@ |
|||
package com.bx.implatform.session; |
|||
|
|||
import com.bx.imcommon.enums.IMTerminalType; |
|||
import io.swagger.models.auth.In; |
|||
import lombok.Data; |
|||
|
|||
/* |
|||
* webrtc 会话信息 |
|||
* @Author Blue |
|||
* @Date 2022/10/21 |
|||
*/ |
|||
@Data |
|||
public class WebrtcSession { |
|||
/** |
|||
* 发起者id |
|||
*/ |
|||
private Long callerId; |
|||
/** |
|||
* 发起者终端类型 |
|||
*/ |
|||
private Integer callerTerminal; |
|||
|
|||
/** |
|||
* 接受者id |
|||
*/ |
|||
private Long acceptorId; |
|||
|
|||
/** |
|||
* 接受者终端类型 |
|||
*/ |
|||
private Integer acceptorTerminal; |
|||
} |
|||
File diff suppressed because it is too large
@ -1,28 +1,42 @@ |
|||
package com.bx.implatform.vo; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import com.bx.imcommon.serializer.DateToLongSerializer; |
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import lombok.Data; |
|||
import org.hibernate.validator.constraints.Length; |
|||
|
|||
import javax.validation.constraints.NotEmpty; |
|||
import javax.validation.constraints.NotNull; |
|||
import java.util.Date; |
|||
|
|||
@Data |
|||
@ApiModel("群聊消息VO") |
|||
public class GroupMessageVO { |
|||
|
|||
@NotNull(message="群聊id不可为空") |
|||
@ApiModelProperty(value = "群聊id") |
|||
/* |
|||
* 消息id |
|||
*/ |
|||
private Long id; |
|||
|
|||
/* |
|||
* 群聊id |
|||
*/ |
|||
private Long groupId; |
|||
|
|||
/* |
|||
* 发送者id |
|||
*/ |
|||
private Long sendId; |
|||
|
|||
@Length(max=1024,message = "内容长度不得大于1024") |
|||
@NotEmpty(message="发送内容不可为空") |
|||
@ApiModelProperty(value = "发送内容") |
|||
/* |
|||
* 消息内容 |
|||
*/ |
|||
private String content; |
|||
|
|||
@NotNull(message="消息类型不可为空") |
|||
@ApiModelProperty(value = "消息类型") |
|||
/* |
|||
* 消息内容类型 具体枚举值由应用层定义 |
|||
*/ |
|||
private Integer type; |
|||
|
|||
/** |
|||
* 发送时间 |
|||
*/ |
|||
@JsonSerialize(using = DateToLongSerializer.class) |
|||
private Date sendTime; |
|||
} |
|||
|
|||
@ -1,31 +1,42 @@ |
|||
package com.bx.implatform.vo; |
|||
|
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import com.bx.imcommon.serializer.DateToLongSerializer; |
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import lombok.Data; |
|||
import org.hibernate.validator.constraints.Length; |
|||
|
|||
import javax.validation.constraints.NotEmpty; |
|||
import javax.validation.constraints.NotNull; |
|||
import java.util.Date; |
|||
|
|||
@Data |
|||
@ApiModel("私聊消息VO") |
|||
public class PrivateMessageVO { |
|||
|
|||
/* |
|||
* 消息id |
|||
*/ |
|||
private long id; |
|||
|
|||
@NotNull(message="接收用户id不可为空") |
|||
@ApiModelProperty(value = "接收用户id") |
|||
private Long recvId; |
|||
/* |
|||
* 发送者id |
|||
*/ |
|||
private Long sendId; |
|||
|
|||
/* |
|||
* 接收者id |
|||
*/ |
|||
private Long recvId; |
|||
|
|||
@Length(max=1024,message = "内容长度不得大于1024") |
|||
@NotEmpty(message="发送内容不可为空") |
|||
@ApiModelProperty(value = "发送内容") |
|||
/* |
|||
* 发送内容 |
|||
*/ |
|||
private String content; |
|||
|
|||
@NotNull(message="消息类型不可为空") |
|||
@ApiModelProperty(value = "消息类型") |
|||
/* |
|||
* 消息内容类型 IMCmdType |
|||
*/ |
|||
private Integer type; |
|||
|
|||
/** |
|||
* 发送时间 |
|||
*/ |
|||
@JsonSerialize(using = DateToLongSerializer.class) |
|||
private Date sendTime; |
|||
} |
|||
|
|||
@ -0,0 +1,12 @@ |
|||
package com.bx.imserver.constant; |
|||
|
|||
public class ChannelAttrKey { |
|||
|
|||
// 用户ID
|
|||
public static final String USER_ID = "USER_ID"; |
|||
// 终端类型
|
|||
public static final String TERMINAL_TYPE = "TERMINAL_TYPE"; |
|||
// 心跳次数
|
|||
public static final String HEARTBEAT_TIMES = "HEARTBEAt_TIMES"; |
|||
|
|||
} |
|||
@ -1,45 +1,35 @@ |
|||
package com.bx.imserver.task; |
|||
|
|||
import com.bx.imcommon.contant.RedisKey; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.bx.imcommon.contant.IMRedisKey; |
|||
import com.bx.imcommon.enums.IMCmdType; |
|||
import com.bx.imcommon.model.GroupMessageInfo; |
|||
import com.bx.imcommon.model.IMRecvInfo; |
|||
import com.bx.imserver.netty.IMServerGroup; |
|||
import com.bx.imserver.netty.processor.MessageProcessor; |
|||
import com.bx.imserver.netty.processor.AbstractMessageProcessor; |
|||
import com.bx.imserver.netty.processor.ProcessorFactory; |
|||
import com.bx.imserver.netty.ws.WebSocketServer; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.List; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
public class PullUnreadGroupMessageTask extends AbstractPullMessageTask { |
|||
|
|||
@Autowired |
|||
private WebSocketServer WSServer; |
|||
|
|||
@Autowired |
|||
private RedisTemplate<String,Object> redisTemplate; |
|||
|
|||
|
|||
|
|||
@Override |
|||
public void pullMessage() { |
|||
// 从redis拉取未读消息
|
|||
String key = RedisKey.IM_UNREAD_GROUP_QUEUE + IMServerGroup.serverId; |
|||
List messageInfos = redisTemplate.opsForList().range(key,0,-1); |
|||
for(Object o: messageInfos){ |
|||
redisTemplate.opsForList().leftPop(key); |
|||
IMRecvInfo<GroupMessageInfo> recvInfo = (IMRecvInfo)o; |
|||
MessageProcessor processor = ProcessorFactory.createProcessor(IMCmdType.GROUP_MESSAGE); |
|||
String key = String.join(":", IMRedisKey.IM_UNREAD_GROUP_QUEUE,IMServerGroup.serverId+""); |
|||
JSONObject jsonObject = (JSONObject)redisTemplate.opsForList().leftPop(key,10, TimeUnit.SECONDS); |
|||
if(jsonObject != null){ |
|||
IMRecvInfo recvInfo = jsonObject.toJavaObject(IMRecvInfo.class); |
|||
AbstractMessageProcessor processor = ProcessorFactory.createProcessor(IMCmdType.GROUP_MESSAGE); |
|||
processor.process(recvInfo); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
|
Before Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 62 KiB |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue