All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
cn.blankcat.websocket.WebsocketService Maven / Gradle / Ivy
package cn.blankcat.websocket;
import cn.blankcat.config.BotConfig;
import cn.blankcat.dto.audio.AudioAction;
import cn.blankcat.dto.channel.Channel;
import cn.blankcat.dto.guild.Guild;
import cn.blankcat.dto.member.Member;
import cn.blankcat.dto.message.Message;
import cn.blankcat.dto.websocket.*;
import cn.blankcat.openapi.GatewayService;
import cn.blankcat.openapi.RetrofitManager;
import cn.blankcat.websocket.handler.HelloHandler;
import cn.blankcat.websocket.handler.PlayLoadHandler;
import cn.blankcat.websocket.handler.ReadyHandler;
import cn.blankcat.websocket.handler.WebsocketHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
public class WebsocketService {
private static final AtomicBoolean HeartBeatFlag = new AtomicBoolean(true);
private static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
private static final Logger logger = LoggerFactory.getLogger("websocketService");
public static Map, List> CLASS_HANDLER_MAP = new HashMap<>(){{
put(Guild.class, new ArrayList<>());
put(Message.class, new ArrayList<>());
put(Channel.class, new ArrayList<>());
put(Member.class, new ArrayList<>());
put(AudioAction.class, new ArrayList<>());
put(WSReadyData.class, new ArrayList<>(){{add(new ReadyHandler());}});
put(WSHelloData.class, new ArrayList<>(){{add(new HelloHandler());}});
put(WSPayload.class, new ArrayList<>(){{add(new PlayLoadHandler());}});
}};
/**
* 根据用户设置的intents, 分片信息, 进行鉴权
* @param intents 要订阅的事件, 可以通过WSEvent.allEventToIntent()获取全部订阅事件
* @param nowShard 当前分片
* @param totalShard 总分片
*/
public void checkIdentity(int intents, long nowShard, long totalShard){
List shardList = new ArrayList<>() {{
add(nowShard);
add(totalShard);
}};
WebSocket webSocket = WebsocketManager.getInstance();
WSIdentityData wsIdentityData = new WSIdentityData();
wsIdentityData.setIntents(intents);
wsIdentityData.setToken(BotConfig.DEFAULT.formatBetterToken());
wsIdentityData.setShard(shardList);
WSPayload wsPayload = new WSPayload<>();
wsPayload.setOpCode(WSPayload.OPCode.WSIdentity.getValue());
wsPayload.setData(wsIdentityData);
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(wsPayload);
webSocket.send(json);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
logger.info("正在获取新的session");
}
private void resume(){
// 构建数据
WSResumeData wsResumeData = new WSResumeData();
wsResumeData.setToken(BotConfig.DEFAULT.formatBetterToken());
wsResumeData.setSessionId(BotConfig.DEFAULT.getSessionId());
wsResumeData.setSeq(BotConfig.DEFAULT.getSeq());
// 构建playload
WSPayload wsPayload = new WSPayload<>();
wsPayload.setOpCode(WSPayload.OPCode.WSResume.getValue());
wsPayload.setSeq(BotConfig.DEFAULT.getSeq());
wsPayload.setData(wsResumeData);
try {
WebsocketManager.getInstance().send(new ObjectMapper().writeValueAsString(wsPayload));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
logger.info("正在恢复连接");
}
/**
* 自动订阅所有事件, 同时根据配置文件中的分片信息, 进行websocket连接, 包含自动重连, 心跳和鉴权
*/
public void connect() {
connect(WSEvent.allEventToIntent(), BotConfig.DEFAULT.getNowShard(), BotConfig.DEFAULT.getTotalShard());
}
/**
* 根据用户设置的intents, 以及配置文件中的分片信息, 进行websocket连接, 包含自动重连, 心跳和鉴权
* @param intents 要订阅的事件, 可以通过WSEvent.allEventToIntent()获取全部订阅事件
*/
public void connect(int intents) {
connect(intents, BotConfig.DEFAULT.getNowShard(), BotConfig.DEFAULT.getTotalShard());
}
/**
* 根据用户设置的intents, 分片信息, 进行websocket连接, 包含自动重连, 心跳和鉴权
* @param intents 要订阅的事件, 可以通过WSEvent.allEventToIntent()获取全部订阅事件
* @param nowShard 当前分片
* @param totalShard 总分片
*/
public void connect(int intents, long nowShard, long totalShard){
try {
WebsocketAP result = RetrofitManager.getInstance().create(GatewayService.class).getWebsocketGatewayAP().execute().body();
// 如果重置了那么直接获取新的session, 否则使用旧的session恢复连接
if (Objects.requireNonNull(result).getSessionStartLimit().getTotal() == result.getSessionStartLimit().getRemaining()
|| BotConfig.DEFAULT.getSessionId() == null
|| BotConfig.DEFAULT.getSessionId().isEmpty()) {
checkIdentity(intents, nowShard, totalShard);
}else {
resume();
}
newThreadKeepHeart();
} catch (IOException e) {
e.printStackTrace();
}
}
private void keepHeart() {
logger.info("启动心跳进程成功, 当前是否显示心跳信息为{}(无论是否显示都会发送心跳)", BotConfig.DEFAULT.getDisplayHeart());
Timer timer = new Timer();
ObjectMapper mapper = new ObjectMapper();
WebSocket webSocket = WebsocketManager.getInstance();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 持续发送心跳
if (HeartBeatFlag.get()) {
WSPayload wsPayload = new WSPayload();
wsPayload.setOpCode(WSPayload.OPCode.WSHeartbeat.getValue());
wsPayload.setData(BotConfig.DEFAULT.getSeq());
try {
webSocket.send(mapper.writeValueAsString(wsPayload));
if (BotConfig.DEFAULT.getDisplayHeart()) {
logger.info("发送心跳成功");
}
// 定时保存配置
BotConfig.storeTo(BotConfig.DEFAULT, null);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
}, 1000, BotConfig.DEFAULT.getLastDelay() * 4/ 5);
}
private void newThreadKeepHeart(){
fixedThreadPool.execute(this::keepHeart);
}
/**
* 切换控制是否发送心跳
*/
public void switchHeartFlag(){
HeartBeatFlag.set(!HeartBeatFlag.get());
}
}