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.
com.hiczp.bilibili.api.live.socket.handler.LiveClientHandler Maven / Gradle / Ivy
package com.hiczp.bilibili.api.live.socket.handler;
import com.google.common.eventbus.EventBus;
import com.google.gson.*;
import com.hiczp.bilibili.api.live.socket.LiveClient;
import com.hiczp.bilibili.api.live.socket.Package;
import com.hiczp.bilibili.api.live.socket.PackageHelper;
import com.hiczp.bilibili.api.live.socket.entity.*;
import com.hiczp.bilibili.api.live.socket.event.*;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public class LiveClientHandler extends SimpleChannelInboundHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(LiveClientHandler.class);
private static final Gson GSON = new Gson();
private static final JsonParser JSON_PARSER = new JsonParser();
private final LiveClient liveClient;
private final EventBus eventBus;
private final long roomId;
private final long userId;
public LiveClientHandler(LiveClient liveClient, long roomId, long userId) {
this.liveClient = liveClient;
this.eventBus = liveClient.getEventBus();
this.roomId = roomId;
this.userId = userId;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
LOGGER.debug("Sending Enter Room package");
ctx.writeAndFlush(PackageHelper.createEnterRoomPackage(roomId, userId));
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
eventBus.post(new ConnectionCloseEvent(liveClient));
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
super.userEventTriggered(ctx, evt);
if (evt instanceof IdleStateEvent) {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
if (idleStateEvent.state() == IdleState.READER_IDLE) {
ctx.close();
}
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Package msg) throws Exception {
switch (msg.getPackageType()) {
case DATA: {
JsonObject jsonObject;
String cmd;
try {
//强制使用 UTF-8, 避免在 NT 平台可能出现的乱码问题
jsonObject = JSON_PARSER.parse(new InputStreamReader(new ByteArrayInputStream(msg.getContent()), StandardCharsets.UTF_8))
.getAsJsonObject();
cmd = jsonObject.get("cmd").getAsString();
} catch (JsonSyntaxException | IllegalStateException | NullPointerException e) {
LOGGER.error("Receive invalid json: \n{}", new String(msg.getContent(), StandardCharsets.UTF_8));
e.printStackTrace();
break;
}
eventBus.post(new ReceiveDataPackageDebugEvent(liveClient, jsonObject, cmd));
Supplier eventCreationExpression; //try 不能写在 switch 外面, 用 lambda 来延迟执行
switch (cmd) {
//弹幕消息
case "DANMU_MSG": {
eventCreationExpression = () -> new DanMuMsgPackageEvent(liveClient, GSON.fromJson(jsonObject, DanMuMsgEntity.class));
}
break;
//送礼
case "SEND_GIFT": {
eventCreationExpression = () -> new SendGiftPackageEvent(liveClient, GSON.fromJson(jsonObject, SendGiftEntity.class));
}
break;
//欢迎
case "WELCOME": {
eventCreationExpression = () -> new WelcomePackageEvent(liveClient, GSON.fromJson(jsonObject, WelcomeEntity.class));
}
break;
//许愿瓶
case "WISH_BOTTLE": {
eventCreationExpression = () -> new WishBottlePackageEvent(liveClient, GSON.fromJson(jsonObject, WishBottleEntity.class));
}
break;
//欢迎(舰队)
case "WELCOME_GUARD": {
eventCreationExpression = () -> new WelcomeGuardPackageEvent(liveClient, GSON.fromJson(jsonObject, WelcomeGuardEntity.class));
}
break;
//系统消息(小电视等)
case "SYS_MSG": {
eventCreationExpression = () -> new SysMsgPackageEvent(liveClient, GSON.fromJson(jsonObject, SysMsgEntity.class));
}
break;
//系统礼物(节奏风暴, 活动抽奖等)
case "SYS_GIFT": {
eventCreationExpression = () -> new SysGiftPackageEvent(liveClient, GSON.fromJson(jsonObject, SysGiftEntity.class));
}
break;
//活动事件
case "ACTIVITY_EVENT": {
eventCreationExpression = () -> new ActivityEventPackageEvent(liveClient, GSON.fromJson(jsonObject, ActivityEventEntity.class));
}
break;
//节奏风暴(20 倍以下的)
case "SPECIAL_GIFT": {
eventCreationExpression = () -> new SpecialGiftPackageEvent(liveClient, GSON.fromJson(jsonObject, SpecialGiftEntity.class));
}
break;
//抽奖开始(小奖, 通常是不定期活动)
case "RAFFLE_START": {
eventCreationExpression = () -> new RaffleStartPackageEvent(liveClient, GSON.fromJson(jsonObject, RaffleStartEntity.class));
}
break;
//抽奖结束
case "RAFFLE_END": {
eventCreationExpression = () -> new RaffleEndPackageEvent(liveClient, GSON.fromJson(jsonObject, RaffleEndEntity.class));
}
break;
//TODO 尚不明确 EVENT_CMD 的含义
case "EVENT_CMD": {
eventCreationExpression = () -> new EventCmdPackageEvent(liveClient, GSON.fromJson(jsonObject, EventCmdEntity.class));
}
break;
//房间黑名单(房间管理员添加了一个用户到黑名单)
case "ROOM_BLOCK_MSG": {
eventCreationExpression = () -> new RoomBlockMsgPackageEvent(liveClient, GSON.fromJson(jsonObject, RoomBlockMsgEntity.class));
}
break;
//房间开启了禁言(禁止某一等级以下的用户发言)
case "ROOM_SILENT_ON": {
eventCreationExpression = () -> new RoomSilentOnPackageEvent(liveClient, GSON.fromJson(jsonObject, RoomSilentOnEntity.class));
}
break;
//房间结束禁言
case "ROOM_SILENT_OFF": {
eventCreationExpression = () -> new RoomSilentOffPackageEvent(liveClient, GSON.fromJson(jsonObject, RoomSilentOffEntity.class));
}
break;
//船票购买
case "GUARD_BUY": {
eventCreationExpression = () -> new GuardBuyPackageEvent(liveClient, GSON.fromJson(jsonObject, GuardBuyEntity.class));
}
break;
//舰队消息(登船)
case "GUARD_MSG": {
eventCreationExpression = () -> new GuardMsgPackageEvent(liveClient, GSON.fromJson(jsonObject, GuardMsgEntity.class));
}
break;
//小电视抽奖开始
case "TV_START": {
eventCreationExpression = () -> new TVStartPackageEvent(liveClient, GSON.fromJson(jsonObject, TVStartEntity.class));
}
break;
//小电视抽奖结束(大奖的获得者信息)
case "TV_END": {
eventCreationExpression = () -> new TVEndPackageEvent(liveClient, GSON.fromJson(jsonObject, TVEndEntity.class));
}
break;
//小时榜
case "ROOM_RANK": {
eventCreationExpression = () -> new RoomRankPackageEvent(liveClient, GSON.fromJson(jsonObject, RoomRankEntity.class));
}
break;
//欢迎(活动)
case "WELCOME_ACTIVITY": {
eventCreationExpression = () -> new WelcomeActivityPackageEvent(liveClient, GSON.fromJson(jsonObject, WelcomeActivityEntity.class));
}
break;
//房管变更
case "ROOM_ADMINS": {
eventCreationExpression = () -> new RoomAdminsPackageEvent(liveClient, GSON.fromJson(jsonObject, RoomAdminsEntity.class));
}
break;
//开始直播
case "LIVE": {
eventCreationExpression = () -> new LivePackageEvent(liveClient, GSON.fromJson(jsonObject, LiveEntity.class));
}
break;
//停止直播
case "PREPARING": {
eventCreationExpression = () -> new PreparingPackageEvent(liveClient, GSON.fromJson(jsonObject, PreparingEntity.class));
}
break;
//房间屏蔽
case "ROOM_SHIELD": {
eventCreationExpression = () -> new RoomShieldPackageEvent(liveClient, GSON.fromJson(jsonObject, RoomShieldEntity.class));
}
break;
//更换房间背景图片
case "CHANGE_ROOM_INFO": {
eventCreationExpression = () -> new ChangeRoomInfoPackageEvent(liveClient, GSON.fromJson(jsonObject, ChangeRoomInfoEntity.class));
}
break;
//被 B站 管理员强制中断
case "CUT_OFF": {
eventCreationExpression = () -> new CutOffPackageEvent(liveClient, GSON.fromJson(jsonObject, CutOffEntity.class));
}
break;
//房间被封
case "ROOM_LOCK": {
eventCreationExpression = () -> new RoomLockPackageEvent(liveClient, GSON.fromJson(jsonObject, RoomLockEntity.class));
}
break;
default: {
LOGGER.error("Received unknown json below: \n{}", formatJson(jsonObject));
eventCreationExpression = () -> new UnknownPackageEvent(liveClient, jsonObject);
}
break;
}
try {
eventBus.post(eventCreationExpression.get());
} catch (JsonParseException e) {
LOGGER.error("Json parse error: {}, json below: \n{}", e.getMessage(), formatJson(jsonObject));
}
}
break;
case VIEWER_COUNT: {
eventBus.post(new ViewerCountPackageEvent(liveClient, ByteBuffer.wrap(msg.getContent()).getInt()));
}
break;
case ENTER_ROOM_SUCCESS: {
eventBus.post(new ConnectSucceedEvent(liveClient));
ctx.executor().scheduleAtFixedRate(
() -> {
ctx.writeAndFlush(PackageHelper.createHeartBeatPackage());
eventBus.post(new SendHeartBeatPackageEvent(liveClient));
},
0L,
30L,
TimeUnit.SECONDS
);
}
break;
}
}
private String formatJson(JsonElement jsonElement) {
return new GsonBuilder()
.setPrettyPrinting()
.create()
.toJson(jsonElement);
}
}