mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-16 13:23:42 +00:00
init v1.0.0
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
### 序列化
|
||||
|
||||
#### 序列化基本数据类型
|
||||
|
||||
1. escape(key)
|
||||
2. escape(value)
|
||||
3. key@=value/
|
||||
|
||||
#### 序列化Map
|
||||
|
||||
1. escape(key)
|
||||
2. value for each
|
||||
1. escape(key)
|
||||
2. escape(value)
|
||||
3. escape(key@=value/)
|
||||
3. escape(value)
|
||||
4. key@=value/
|
||||
|
||||
### 反序列化
|
||||
|
||||
#### 反序列化基本数据类型
|
||||
|
||||
1. spilt("/"):
|
||||
type@=chatmsg
|
||||
|
||||
2. split("@="):
|
||||
1. key: unescape(key) = el
|
||||
2. unescape(value).endsWith("/") = false
|
||||
2.1 value = chatmsg
|
||||
|
||||
#### 反序列化Map
|
||||
|
||||
1. spilt("/"):
|
||||
el@=eid@AA=1@ASetp@AA=1@ASsc@AA=1@AS
|
||||
|
||||
2. split("@="):
|
||||
1. key: unescape = el
|
||||
2. unescape(value).endsWith("/") = true
|
||||
eid@A=1/etp@A=1/sc@A=1/
|
||||
1. split("/")
|
||||
eid@A=1
|
||||
etp@A=1
|
||||
sc@A=1
|
||||
2. unescape:
|
||||
eid@=1
|
||||
etp@=1
|
||||
sc@=1
|
||||
3. for each
|
||||
1. split("@=")
|
||||
2. unescape(key)
|
||||
3. unescape(value)
|
||||
4. value: map
|
||||
@@ -0,0 +1,60 @@
|
||||
<!--
|
||||
~ MIT License
|
||||
~
|
||||
~ Copyright (c) 2023 OrdinaryRoad
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in all
|
||||
~ copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
~ SOFTWARE.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-clients</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-douyu</artifactId>
|
||||
<name>live-chat-client-douyu</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-servers-netty-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${junit-jupiter.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.api;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import cn.hutool.http.*;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.Cleanup;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLocalDateTimeUtil;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftPropSingle;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* API简易版
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/5/5
|
||||
*/
|
||||
@Slf4j
|
||||
public class DouyuApis {
|
||||
|
||||
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
public static final String PATTERN_BODY_ROOM_ID = "\\$ROOM\\.room_id\\D+(\\d+)";
|
||||
public static final String KEY_REDIRECT_LOCATION_RID = "rid";
|
||||
public static final String KEY_COOKIE_DY_DID = "dy_did";
|
||||
public static final String KEY_COOKIE_ACF_UID = "acf_uid";
|
||||
public static final String KEY_COOKIE_ACF_STK = "acf_stk";
|
||||
public static final String KEY_COOKIE_ACF_LTKID = "acf_ltkid";
|
||||
public static final String API_AVATAR = "https://apic.douyucdn.cn/upload/";
|
||||
// https://webconf.douyucdn.cn/resource/common/gift/flash/gift_effect.json
|
||||
// https://webconf.douyucdn.cn/resource/common/gift/common_config_v2.json
|
||||
// https://webconf.douyucdn.cn/resource/common/prop_gift_list/prop_gift_config.json
|
||||
// 用PID查询礼物信息:https://gift.douyucdn.cn/api/prop/v1/web/single?pid=
|
||||
// 查询房间礼物列表:https://gift.douyucdn.cn/api/gift/v3/web/list?rid=
|
||||
public static final String API_GIFT_LIST = "https://gift.douyucdn.cn/api/gift/v3/web/list?rid=";
|
||||
public static final String API_PROP_SINGLE = "https://gift.douyucdn.cn/api/prop/v1/web/single?pid=";
|
||||
public static final String API_AVATAR_PREFIX_SMALL = "_small.jpg";
|
||||
public static final String API_AVATAR_PREFIX_MIDDLE = "_middle.jpg";
|
||||
public static final String API_AVATAR_PREFIX_BIG = "_big.jpg";
|
||||
|
||||
public static String getAvatarUrl(List<String> list, String prefix) {
|
||||
if (CollUtil.isEmpty(list) || list.size() < 3) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
return API_AVATAR + CollUtil.join(list, "/") + prefix;
|
||||
}
|
||||
|
||||
public static String getSmallAvatarUrl(List<String> list) {
|
||||
return getAvatarUrl(list, API_AVATAR_PREFIX_SMALL);
|
||||
}
|
||||
|
||||
public static long getRealRoomId(long roomId, String cookie) {
|
||||
String realRoomIdString = null;
|
||||
@Cleanup
|
||||
HttpResponse execute = createGetRequest("https://www.douyu.com/" + roomId, cookie).execute();
|
||||
if (execute.getStatus() == HttpStatus.HTTP_NOT_FOUND) {
|
||||
throw new BaseException("获取" + roomId + "真实房间ID失败");
|
||||
}
|
||||
if (HttpStatus.isRedirected(execute.getStatus())) {
|
||||
String location = execute.header(Header.LOCATION);
|
||||
Map<String, String> paramMap = HttpUtil.decodeParamMap(location, null);
|
||||
if (paramMap.containsKey(KEY_REDIRECT_LOCATION_RID)) {
|
||||
realRoomIdString = paramMap.get(KEY_REDIRECT_LOCATION_RID);
|
||||
}
|
||||
}
|
||||
if (StrUtil.isBlank(realRoomIdString)) {
|
||||
String body = execute.body();
|
||||
String matchString = ReUtil.get(PATTERN_BODY_ROOM_ID, body, 1);
|
||||
if (StrUtil.isNotBlank(matchString)) {
|
||||
realRoomIdString = matchString;
|
||||
}
|
||||
}
|
||||
long realRoomId = roomId;
|
||||
if (!StrUtil.isBlank(realRoomIdString)) {
|
||||
try {
|
||||
realRoomId = NumberUtil.parseLong(realRoomIdString);
|
||||
} catch (Exception e) {
|
||||
throw new BaseException("获取" + roomId + "真实房间ID失败");
|
||||
}
|
||||
}
|
||||
return realRoomId;
|
||||
}
|
||||
|
||||
public static long getRealRoomId(long roomId) {
|
||||
return getRealRoomId(roomId, null);
|
||||
}
|
||||
|
||||
public static JsonNode getServerInfo(long roomId, String cookie) {
|
||||
@Cleanup
|
||||
HttpResponse execute = createPostRequest("https://www.douyu.com/lapi/live/gateway/web/" + roomId + "?isH5=1", cookie).execute();
|
||||
return responseInterceptor(execute.body());
|
||||
}
|
||||
|
||||
public static JsonNode getServerInfo(long roomId) {
|
||||
return getServerInfo(roomId, null);
|
||||
}
|
||||
|
||||
public static String getRandomWssUri(long roomId) {
|
||||
JsonNode serverInfo = getServerInfo(roomId);
|
||||
JsonNode wss = serverInfo.get("wss");
|
||||
JsonNode jsonNode = wss.get(RandomUtil.randomInt(0, wss.size()));
|
||||
return "wss://" + jsonNode.get("domain").asText() + ":" + jsonNode.get("port").asInt();
|
||||
}
|
||||
|
||||
public static JsonNode getGiftList(long roomId) {
|
||||
@Cleanup
|
||||
HttpResponse execute = createGetRequest(API_GIFT_LIST + roomId, null).execute();
|
||||
return responseInterceptor(execute.body());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static GiftPropSingle getGiftPropSingleByPid(String pid) {
|
||||
@Cleanup
|
||||
HttpResponse execute = createGetRequest(API_PROP_SINGLE + pid, null).execute();
|
||||
JsonNode jsonNode = responseInterceptor(execute.body());
|
||||
return BaseMsg.OBJECT_MAPPER.readValue(jsonNode.toString(), GiftPropSingle.class);
|
||||
}
|
||||
|
||||
public static final String vk_secret = "r5*^5;}2#${XF[h+;'./.Q'1;,-]f'p[";
|
||||
|
||||
/**
|
||||
* 参考: <a href="https://cjting.me/2020/07/01/douyu-crawler-and-font-anti-crawling">斗鱼关注人数爬取 ── 字体反爬的攻与防</a>
|
||||
*
|
||||
* @param currentTimeSecs
|
||||
* @param did
|
||||
* @return
|
||||
*/
|
||||
public static String generateVk(long currentTimeSecs, String did) {
|
||||
return MD5.create().digestHex(currentTimeSecs + vk_secret + did);
|
||||
}
|
||||
|
||||
public static String generateVk(String did) {
|
||||
return generateVk(OrLocalDateTimeUtil.zonedCurrentTimeSecs(), did);
|
||||
}
|
||||
|
||||
public static HttpRequest createGetRequest(String url, String cookie) {
|
||||
return HttpUtil.createGet(url)
|
||||
.cookie(cookie);
|
||||
}
|
||||
|
||||
public static HttpRequest createPostRequest(String url, String cookie) {
|
||||
return HttpUtil.createPost(url)
|
||||
.cookie(cookie);
|
||||
}
|
||||
|
||||
private static JsonNode responseInterceptor(String responseString) {
|
||||
try {
|
||||
JsonNode jsonNode = OBJECT_MAPPER.readTree(responseString);
|
||||
int code = jsonNode.get("error").asInt();
|
||||
if (code == 0) {
|
||||
// 成功
|
||||
return jsonNode.get("data");
|
||||
} else {
|
||||
throw new BaseException(jsonNode.get("msg").asText());
|
||||
}
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.client.base.BaseDouyuLiveChatClient;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.config.DouyuLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuClientModeEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.LoginresMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuConnectionHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 直播间弹幕客户端{@link DouyuClientModeEnum#DANMU}
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/20
|
||||
*/
|
||||
@Slf4j
|
||||
public class DouyuDanmuLiveChatClient extends BaseDouyuLiveChatClient implements IDouyuMsgListener {
|
||||
|
||||
public DouyuDanmuLiveChatClient(DouyuLiveChatClientConfig config, List<IDouyuMsgListener> msgListeners, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(DouyuClientModeEnum.DANMU, config, msgListeners, connectionListener, workerGroup);
|
||||
addMsgListener(DouyuDanmuLiveChatClient.this);
|
||||
}
|
||||
|
||||
public DouyuDanmuLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(DouyuClientModeEnum.DANMU, config, msgListener, connectionListener, workerGroup);
|
||||
addMsgListener(DouyuDanmuLiveChatClient.this);
|
||||
}
|
||||
|
||||
public DouyuDanmuLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener) {
|
||||
this(config, msgListener, connectionListener, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public DouyuDanmuLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener) {
|
||||
this(config, msgListener, null);
|
||||
}
|
||||
|
||||
public DouyuDanmuLiveChatClient(DouyuLiveChatClientConfig config) {
|
||||
this(config, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DouyuConnectionHandler initConnectionHandler(IBaseConnectionListener<DouyuConnectionHandler> clientConnectionListener) {
|
||||
return new DouyuConnectionHandler(DouyuClientModeEnum.DANMU,
|
||||
WebSocketClientHandshakerFactory.newHandshaker(getWebsocketUri(), WebSocketVersion.V13, null, true, new DefaultHttpHeaders(), getConfig().getMaxFramePayloadLength()),
|
||||
DouyuDanmuLiveChatClient.this, clientConnectionListener
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DouyuBinaryFrameHandler initBinaryFrameHandler() {
|
||||
return new DouyuBinaryFrameHandler(msgListeners, DouyuDanmuLiveChatClient.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
if (msg instanceof LoginresMsg) {
|
||||
// 1 type@=joingroup/rid@=4615502/gid@=1/
|
||||
send(getWebSocketFrameFactory(getConfig().getRoomId()).createJoingroup(), () -> {
|
||||
// 2 type@=mrkl/
|
||||
send(getWebSocketFrameFactory(getConfig().getRoomId()).createHeartbeat(), () -> {
|
||||
// 3 type@=sub/mt@=dayrk/
|
||||
send(getWebSocketFrameFactory(getConfig().getRoomId()).createSub());
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMsgListener(IDouyuMsgListener msgListener) {
|
||||
if (msgListener == DouyuDanmuLiveChatClient.this) {
|
||||
return false;
|
||||
}
|
||||
return super.removeMsgListener(msgListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllMsgListeners() {
|
||||
super.removeAllMsgListeners();
|
||||
addMsgListener(DouyuDanmuLiveChatClient.this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.ICmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.enums.ClientStatusEnums;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.config.DouyuLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.ChatmsgMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.DgbMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.MsgrepeaterproxylistMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.UenterMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftListInfo;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftPropSingle;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuConnectionHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 直播间弹幕客户端
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/20
|
||||
*/
|
||||
@Slf4j
|
||||
public class DouyuLiveChatClient extends DouyuWsLiveChatClient implements IDouyuMsgListener {
|
||||
|
||||
/**
|
||||
* 通用礼物缓存,过期时间1天
|
||||
* pid,Info
|
||||
*/
|
||||
public static final TimedCache<String, GiftPropSingle> giftMap = new TimedCache<>(TimeUnit.DAYS.toMillis(1));
|
||||
/**
|
||||
* 房间礼物缓存,过期时间1天
|
||||
* realRoomId,(giftId,Info)
|
||||
*/
|
||||
public static final TimedCache<String, Map<String, GiftListInfo>> roomGiftMap = new TimedCache<>(TimeUnit.DAYS.toMillis(1), new HashMap<>());
|
||||
private final DouyuWsLiveChatClient proxyClient = this;
|
||||
private DouyuDanmuLiveChatClient danmuClient = null;
|
||||
private DouyuConnectionHandler connectionHandler;
|
||||
/**
|
||||
* 统一管理Ws、Danmu的连接状态
|
||||
*/
|
||||
private final IDouyuConnectionListener connectionListener;
|
||||
|
||||
public DouyuLiveChatClient(DouyuLiveChatClientConfig config, List<IDouyuMsgListener> msgListeners, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, msgListeners, null, workerGroup);
|
||||
this.connectionListener = connectionListener;
|
||||
}
|
||||
|
||||
public DouyuLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, msgListener, null, workerGroup);
|
||||
this.connectionListener = connectionListener;
|
||||
}
|
||||
|
||||
public DouyuLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener) {
|
||||
this(config, msgListener, connectionListener, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public DouyuLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener) {
|
||||
this(config, msgListener, null);
|
||||
}
|
||||
|
||||
public DouyuLiveChatClient(DouyuLiveChatClientConfig config) {
|
||||
this(config, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
|
||||
// 初始化房间礼物列表
|
||||
Map<String, GiftListInfo> map = new HashMap<>();
|
||||
DouyuApis.getGiftList(getConfig().getRoomId())
|
||||
.get("giftList")
|
||||
.forEach(jsonNode -> {
|
||||
try {
|
||||
GiftListInfo giftListInfo = BaseMsg.OBJECT_MAPPER.readValue(jsonNode.toString(), GiftListInfo.class);
|
||||
map.put(String.valueOf(giftListInfo.getId()), giftListInfo);
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("获取房间礼物列表异常", e);
|
||||
}
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
roomGiftMap.put(String.valueOf(DouyuApis.getRealRoomId(getConfig().getRoomId())), map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DouyuConnectionHandler initConnectionHandler(IBaseConnectionListener<DouyuConnectionHandler> clientConnectionListener) {
|
||||
this.connectionHandler = super.initConnectionHandler(super.clientConnectionListener);
|
||||
return connectionHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
super.onMsg(binaryFrameHandler, msg);
|
||||
if (msg instanceof MsgrepeaterproxylistMsg) {
|
||||
MsgrepeaterproxylistMsg msgrepeaterproxylistMsg = (MsgrepeaterproxylistMsg) msg;
|
||||
List<Map<String, String>> list = msgrepeaterproxylistMsg.getList();
|
||||
if (list.isEmpty()) {
|
||||
log.error("弹幕服务器列表为空");
|
||||
if (connectionListener != null) {
|
||||
connectionListener.onConnectFailed(connectionHandler);
|
||||
}
|
||||
disconnect();
|
||||
} else {
|
||||
// 初始化danmuClient
|
||||
int randomIndex = RandomUtil.randomInt(0, list.size());
|
||||
Map<String, String> randomMap = list.get(randomIndex);
|
||||
DouyuLiveChatClientConfig danmuClientConfig = BeanUtil.toBean(getConfig(), DouyuLiveChatClientConfig.class, CopyOptions.create().ignoreNullValue());
|
||||
danmuClientConfig.setWebsocketUri(String.format("wss://%s:%s/", randomMap.get("ip"), randomMap.get("port")));
|
||||
destroyDanmuClient();
|
||||
this.danmuClient = new DouyuDanmuLiveChatClient(danmuClientConfig, new IDouyuMsgListener() {
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onMsg(binaryFrameHandler, msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDanmuMsg(DouyuBinaryFrameHandler binaryFrameHandler, ChatmsgMsg msg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onDanmuMsg(binaryFrameHandler, msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGiftMsg(DouyuBinaryFrameHandler binaryFrameHandler, DgbMsg msg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onGiftMsg(binaryFrameHandler, msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterRoomMsg(DouyuBinaryFrameHandler binaryFrameHandler, UenterMsg uenterMsg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onEnterRoomMsg(binaryFrameHandler, uenterMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCmdMsg(DouyuBinaryFrameHandler binaryFrameHandler, DouyuCmdEnum cmd, ICmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onCmdMsg(binaryFrameHandler, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOtherCmdMsg(DouyuBinaryFrameHandler binaryFrameHandler, DouyuCmdEnum cmd, ICmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onOtherCmdMsg(binaryFrameHandler, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnknownCmd(DouyuBinaryFrameHandler binaryFrameHandler, String cmdString, IMsg msg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onUnknownCmd(binaryFrameHandler, cmdString, msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCmdMsg(DouyuBinaryFrameHandler binaryFrameHandler, DouyuCmdEnum cmd, BaseCmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onCmdMsg(binaryFrameHandler, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOtherCmdMsg(DouyuBinaryFrameHandler binaryFrameHandler, DouyuCmdEnum cmd, BaseCmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onOtherCmdMsg(binaryFrameHandler, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnknownCmd(DouyuBinaryFrameHandler binaryFrameHandler, String cmdString, BaseMsg msg) {
|
||||
proxyClient.iteratorMsgListeners(msgListener -> msgListener.onUnknownCmd(binaryFrameHandler, cmdString, msg));
|
||||
}
|
||||
}, new IDouyuConnectionListener() {
|
||||
@Override
|
||||
public void onConnected(DouyuConnectionHandler connectionHandler) {
|
||||
if (connectionListener != null) {
|
||||
connectionListener.onConnected(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailed(DouyuConnectionHandler connectionHandler) {
|
||||
if (connectionListener != null) {
|
||||
connectionListener.onConnectFailed(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(DouyuConnectionHandler connectionHandler) {
|
||||
if (connectionListener != null) {
|
||||
connectionListener.onDisconnected(connectionHandler);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.danmuClient.addStatusChangeListener(evt -> {
|
||||
ClientStatusEnums newStatus = (ClientStatusEnums) evt.getNewValue();
|
||||
switch (newStatus) {
|
||||
case CONNECTED:
|
||||
case RECONNECTING:
|
||||
case CONNECT_FAILED:
|
||||
case DISCONNECTED:
|
||||
case CONNECTING: {
|
||||
super.setStatus(newStatus);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
this.danmuClient.connect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setStatus(ClientStatusEnums status) {
|
||||
if (status == ClientStatusEnums.CONNECTED) {
|
||||
return;
|
||||
}
|
||||
super.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
destroyDanmuClient();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
private void destroyDanmuClient() {
|
||||
if (danmuClient != null) {
|
||||
danmuClient.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.client.base.BaseDouyuLiveChatClient;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.config.DouyuLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuClientModeEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.LoginresMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuConnectionHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 直播间弹幕客户端{@link DouyuClientModeEnum#WS}
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/20
|
||||
*/
|
||||
@Slf4j
|
||||
public class DouyuWsLiveChatClient extends BaseDouyuLiveChatClient implements IDouyuMsgListener {
|
||||
|
||||
public DouyuWsLiveChatClient(DouyuLiveChatClientConfig config, List<IDouyuMsgListener> msgListeners, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(DouyuClientModeEnum.WS, config, msgListeners, connectionListener, workerGroup);
|
||||
addMsgListener(DouyuWsLiveChatClient.this);
|
||||
}
|
||||
|
||||
public DouyuWsLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(DouyuClientModeEnum.WS, config, msgListener, connectionListener, workerGroup);
|
||||
addMsgListener(DouyuWsLiveChatClient.this);
|
||||
}
|
||||
|
||||
public DouyuWsLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener) {
|
||||
this(config, msgListener, connectionListener, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public DouyuWsLiveChatClient(DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener) {
|
||||
this(config, msgListener, null);
|
||||
}
|
||||
|
||||
public DouyuWsLiveChatClient(DouyuLiveChatClientConfig config) {
|
||||
this(config, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getWebSocketUriString() {
|
||||
return DouyuApis.getRandomWssUri(getConfig().getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DouyuConnectionHandler initConnectionHandler(IBaseConnectionListener<DouyuConnectionHandler> clientConnectionListener) {
|
||||
return new DouyuConnectionHandler(DouyuClientModeEnum.WS,
|
||||
WebSocketClientHandshakerFactory.newHandshaker(getWebsocketUri(), WebSocketVersion.V13, null, true, new DefaultHttpHeaders(), getConfig().getMaxFramePayloadLength()),
|
||||
DouyuWsLiveChatClient.this, clientConnectionListener
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DouyuBinaryFrameHandler initBinaryFrameHandler() {
|
||||
return new DouyuBinaryFrameHandler(msgListeners, DouyuWsLiveChatClient.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
if (msg instanceof LoginresMsg) {
|
||||
send(getWebSocketFrameFactory(getConfig().getRoomId()).createKeeplive(getConfig().getCookie()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMsgListener(IDouyuMsgListener msgListener) {
|
||||
if (msgListener == DouyuWsLiveChatClient.this) {
|
||||
return false;
|
||||
}
|
||||
return super.removeMsgListener(msgListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllMsgListeners() {
|
||||
super.removeAllMsgListeners();
|
||||
addMsgListener(DouyuWsLiveChatClient.this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client.base;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.config.DouyuLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuClientModeEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.IDouyuMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.factory.DouyuWebSocketFrameFactory;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuConnectionHandler;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.base.BaseNettyClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/15
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseDouyuLiveChatClient extends BaseNettyClient<
|
||||
DouyuLiveChatClientConfig,
|
||||
DouyuCmdEnum,
|
||||
IDouyuMsg,
|
||||
IDouyuMsgListener,
|
||||
DouyuConnectionHandler,
|
||||
DouyuBinaryFrameHandler
|
||||
> {
|
||||
|
||||
private final DouyuClientModeEnum mode;
|
||||
|
||||
public BaseDouyuLiveChatClient(DouyuClientModeEnum mode, DouyuLiveChatClientConfig config, List<IDouyuMsgListener> msgListeners, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, workerGroup, connectionListener);
|
||||
this.mode = mode;
|
||||
addMsgListeners(msgListeners);
|
||||
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
public BaseDouyuLiveChatClient(DouyuClientModeEnum mode, DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, workerGroup, connectionListener);
|
||||
this.mode = mode;
|
||||
addMsgListener(msgListener);
|
||||
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
public BaseDouyuLiveChatClient(DouyuClientModeEnum mode, DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener, IDouyuConnectionListener connectionListener) {
|
||||
this(mode, config, msgListener, connectionListener, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public BaseDouyuLiveChatClient(DouyuClientModeEnum mode, DouyuLiveChatClientConfig config, IDouyuMsgListener msgListener) {
|
||||
this(mode, config, msgListener, null, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public BaseDouyuLiveChatClient(DouyuClientModeEnum mode, DouyuLiveChatClientConfig config) {
|
||||
this(mode, config, CollUtil.newArrayList(), null, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Runnable success, Consumer<Throwable> failed) {
|
||||
if (!checkCanSendDanmu()) {
|
||||
return;
|
||||
}
|
||||
if (mode == DouyuClientModeEnum.WS && danmu instanceof String) {
|
||||
String msg = (String) danmu;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} douyu发送弹幕 {}", getConfig().getRoomId(), danmu);
|
||||
}
|
||||
|
||||
WebSocketFrame webSocketFrame = null;
|
||||
try {
|
||||
webSocketFrame = getWebSocketFrameFactory(getConfig().getRoomId()).createDanmu(msg, getConfig().getCookie());
|
||||
} catch (Exception e) {
|
||||
log.error("douyu弹幕包创建失败", e);
|
||||
if (failed != null) {
|
||||
failed.accept(e);
|
||||
}
|
||||
}
|
||||
if (webSocketFrame == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
send(webSocketFrame, () -> {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("douyu弹幕发送成功 {}", danmu);
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
finishSendDanmu();
|
||||
}, throwable -> {
|
||||
log.error("douyu弹幕发送失败", throwable);
|
||||
if (failed != null) {
|
||||
failed.accept(throwable);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
super.sendDanmu(danmu);
|
||||
}
|
||||
}
|
||||
|
||||
protected static DouyuWebSocketFrameFactory getWebSocketFrameFactory(long roomId) {
|
||||
return DouyuWebSocketFrameFactory.getInstance(roomId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLiveChatNumberUtil;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.config.BaseNettyClientConfig;
|
||||
|
||||
/**
|
||||
* Douyu直播间弹幕客户端配置
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class DouyuLiveChatClientConfig extends BaseNettyClientConfig {
|
||||
|
||||
@Builder.Default
|
||||
private String ver = "20220825";
|
||||
|
||||
@Builder.Default
|
||||
private String aver = "218101901";
|
||||
|
||||
@Override
|
||||
public Long getRoomId() {
|
||||
return OrLiveChatNumberUtil.parseLong(super.getRoomId());
|
||||
}
|
||||
|
||||
public void setVer(String ver) {
|
||||
String oldValue = this.ver;
|
||||
this.ver = ver;
|
||||
super.propertyChangeSupport.firePropertyChange("ver", oldValue, ver);
|
||||
}
|
||||
|
||||
public void setAver(String aver) {
|
||||
String oldValue = this.aver;
|
||||
this.aver = aver;
|
||||
super.propertyChangeSupport.firePropertyChange("aver", oldValue, aver);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.constant;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/15
|
||||
*/
|
||||
public enum DouyuClientModeEnum {
|
||||
/**
|
||||
* 发送弹幕,获取可用的Danmu服务器链接
|
||||
*/
|
||||
WS,
|
||||
/**
|
||||
* 接收直播间弹幕
|
||||
*/
|
||||
DANMU,
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.constant;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.*;
|
||||
|
||||
/**
|
||||
* <a href='https://open.douyu.com/source/api/63'>文档</a>
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@RequiredArgsConstructor
|
||||
public enum DouyuCmdEnum {
|
||||
/**
|
||||
* 登录请求消息
|
||||
* <pre>{@code
|
||||
* type@=loginreq/roomid@=7750753/dfl@=/username@=visitor10424697/uid@=1168052601/ver@=20220825/aver@=218101901/ct@=0/
|
||||
* type@=loginreq/roomid@=58839/aid@=yihanTest/token@=4c8421535f9639d8c1ad35d1fa421f36/time@=1574850339/auth@=45619bb990e6b76db06a66d5a8a446d7/
|
||||
* }</pre>
|
||||
*/
|
||||
loginreq(LoginreqMsg.class),
|
||||
/**
|
||||
* 登录响应消息
|
||||
* <pre>{@code
|
||||
* type@=loginres/userid@=1168052601/roomgroup@=0/pg@=0/sessionid@=0/username@=/nickname@=/live_stat@=0/is_illegal@=0/ill_ct@=/ill_ts@=0/now@=0/ps@=0/es@=0/it@=0/its@=0/npv@=0/best_dlev@=0/cur_lev@=0/nrc@=964715377/ih@=0/sid@=76494/sahf@=0/sceneid@=0/newrg@=0/regts@=0/ip@=112.43.93.229/rn@=0/rct@=0/
|
||||
* type@=loginresp/msg@=ok/rid@=77614265/
|
||||
* }</pre>
|
||||
*/
|
||||
loginres(LoginresMsg.class),
|
||||
/**
|
||||
* 入组
|
||||
* type@=joingroup/rid@=59872/aid@=yourapplicaitonID/token@=4c8421535f9639d8c1ad35d1fa421f36/time@=1574850339/auth@=xxxxxxxxxxxx/
|
||||
* Auth 生成方式为 md5({secret}_{aid}_{time}_{token}), secret为aid对应的秘钥
|
||||
*/
|
||||
joingroup(JoingroupMsg.class),
|
||||
/**
|
||||
* 客户端旧版心跳、心跳回复
|
||||
* <pre>{@code
|
||||
* type@=keeplive/tick@=1439802131/
|
||||
* }</pre>
|
||||
*/
|
||||
keeplive(KeepliveMsg.class),
|
||||
/**
|
||||
* 客户端新版心跳、心跳回复
|
||||
* <pre>{@code
|
||||
* type@=mrkl/
|
||||
* }</pre>
|
||||
*/
|
||||
mrkl,
|
||||
/**
|
||||
* 订阅贵族排行变动
|
||||
* type@=sub/mt@=online_vip_list/
|
||||
*/
|
||||
sub(SubMsg.class),
|
||||
subres,
|
||||
noble_num_info,
|
||||
oni,
|
||||
postLogin,
|
||||
/**
|
||||
* 弹幕
|
||||
* type@=chatmsg/rid@=7750753/uid@=549977/nn@=一闪一闪亮品品/txt@=冷门歌手哎,声音独特哎/cid@=044c3bf3074b483275a44e0000000000/ic@=avatar@Sdefault@S08/level@=29/sahf@=0/nl@=7/cst@=1693107871294/bnn@=/bl@=0/brid@=0/hc@=/lk@=/dms@=8/pdg@=26/pdk@=86/ext@=/
|
||||
* type@=chatmsg/rid@=58839/ct@=8/hashid@=9LA18ePx4dqW/nn@=test/txt@=666/cid@=1111/ic@=icon/sahf@=0/level@=1/nl@=0/nc@=0/cmt@=0/gt@=0/col@=0/rg@=0/pg@=0/dlv@=0/dc@=0/bdlv@=0/gatin@=0/ chtin@=0/repin@=0/bnn@=test/bl@=0/brid@=58839/hc@=0/ol@=0/rev@=0/hl@=0/ifs@=0/p2p@=0/el@=eid@AA=1@ASetp@AA=1@ASsc@AA=1@AS/
|
||||
*/
|
||||
chatmsg(ChatmsgMsg.class),
|
||||
pingreq,
|
||||
/**
|
||||
* 登出
|
||||
* type@=logout/
|
||||
*/
|
||||
logout,
|
||||
/**
|
||||
* 登录响应
|
||||
* type@=loginresp/msg@=ok/rid@=77614265/
|
||||
*/
|
||||
loginresp,
|
||||
/**
|
||||
* 礼物
|
||||
* type@=dgb/gfid@=1/gs@=59872/gfcnt@=1/hashid@=1/rid@=1/nn@=someone/level@=1/dw@=1/
|
||||
*/
|
||||
dgb(DgbMsg.class),
|
||||
/**
|
||||
* 用户进房通知消息
|
||||
* type@=uenter/rid@=1/ uid@=1/nn@=someone/str@=1/level@=1/el@=eid@AA=1@ASetp@AA=1@ASsc@AA=1@AS@S/
|
||||
*/
|
||||
uenter(UenterMsg.class),
|
||||
/**
|
||||
* 房间开关播提醒
|
||||
* type@=rss/rid@=1/ss@=1/code@=1/rt@=0/notify@=1/endtime@=1/
|
||||
*/
|
||||
rss,
|
||||
/**
|
||||
* 超级弹幕消息
|
||||
* type@=ssd/rid@=1/trid@=1/content@=test/cli tp@=1/url@=test_url/jmptp@=1/
|
||||
*/
|
||||
ssd,
|
||||
/**
|
||||
* 房间内礼物广播
|
||||
* type@=spbc/rid@=1/gfid@=1/sn@=name/dn@=name/gn@=1/gc@=1/gb@=1/es@=1/ eid@=1/
|
||||
*/
|
||||
spbc,
|
||||
/**
|
||||
* 房间宝箱消息
|
||||
* type@=tsgs/rid@=1/gid@=1/gfid@=1/sn@=name/dn@=name/gn@=1/gc@=1/gb@=1/es@=1/gfid@=1/eid@=1/
|
||||
*/
|
||||
tsgs,
|
||||
/**
|
||||
* 房间内 top10 变化消息
|
||||
* type@=rankup/uid@=1/rn@=3/rid@=1/rkt@=1/gid@=-9999/rt@=0/ nk@=test/sz@=3/drid@=1/bt@=1/
|
||||
*/
|
||||
rankup,
|
||||
/**
|
||||
* 主播离开提醒
|
||||
* type@=al/rid@=10111/aid@=3044114/
|
||||
*/
|
||||
al,
|
||||
/**
|
||||
* 主播回来继续直播提醒
|
||||
* type@=ab/rid@=10111/gid@=-9999/aid@=3044114/
|
||||
*/
|
||||
ab,
|
||||
/**
|
||||
* 用户等级提升消息
|
||||
* type@=upgrade/rid@=1/gid@=-9999/uid@=12001/nn@=test/level@=3/ic@=icon/
|
||||
*/
|
||||
upgrade,
|
||||
/**
|
||||
* 主播等级提升广播
|
||||
* type@=upbc/rid@=1/gid@=-9999/lev@=20/pu@=0/
|
||||
*/
|
||||
upbc,
|
||||
/**
|
||||
* 禁言操作结果
|
||||
* type@=newblackres/rid@=1/gid@=-9999/ret@=0/otype@=2/sid@=10002/did@=10003/snic@=stest/dnic@=dtest/endtime@=1501920157/
|
||||
*/
|
||||
newblackres,
|
||||
/**
|
||||
* 徽章等级提升通知
|
||||
* type@=blab/rid@=1/gid@=-9999/uid@=10002/nn@=test/lbl@=2/bl@=3/ba@=1/bnn@=ttt/
|
||||
*/
|
||||
blab,
|
||||
/**
|
||||
* 用户分享了直播间通知
|
||||
* type@=srres/rid@=1/gid@=-9999/uid@=12001/nickname@=test/exp@=3/
|
||||
*/
|
||||
srres,
|
||||
/**
|
||||
* 栏目排行榜变更通知
|
||||
* type@=rri/rid@=1/rn@=cate_rank/cate_id@=5/uid@=10005/sc@=100 00/idx@=10/bcr@=1/ibc@=1/an@=test/rktype@=1/tag_id@=1200/gif t_id@=100/
|
||||
*/
|
||||
rri,
|
||||
mapkb(MapkbMsg.class),
|
||||
/**
|
||||
* 发送弹幕
|
||||
*/
|
||||
chatmessage(ChatmessageMsg.class),
|
||||
h5ckreq(H5ckreqMsg.class),
|
||||
h5gkcreq(H5gkcreqMsg.class),
|
||||
h5cs(H5csMsg.class),
|
||||
msgrepeaterproxylist(MsgrepeaterproxylistMsg.class),
|
||||
;
|
||||
|
||||
private Class<?> tClass;
|
||||
|
||||
public static DouyuCmdEnum getByString(String cmd) {
|
||||
try {
|
||||
return DouyuCmdEnum.valueOf(cmd);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.listener;
|
||||
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuConnectionHandler;
|
||||
|
||||
/**
|
||||
* 连接回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
public interface IDouyuConnectionListener extends IBaseConnectionListener<DouyuConnectionHandler> {
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.listener;
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IDanmuMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IEnterRoomMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IGiftMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.ChatmsgMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.DgbMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.UenterMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuBinaryFrameHandler;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/7
|
||||
*/
|
||||
public interface IDouyuMsgListener extends IBaseMsgListener<DouyuBinaryFrameHandler, DouyuCmdEnum>,
|
||||
IDanmuMsgListener<DouyuBinaryFrameHandler, ChatmsgMsg>,
|
||||
IGiftMsgListener<DouyuBinaryFrameHandler, DgbMsg>,
|
||||
IEnterRoomMsgListener<DouyuBinaryFrameHandler, UenterMsg> {
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLocalDateTimeUtil;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/7
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatmessageMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String pe = "0";
|
||||
/**
|
||||
* 弹幕内容
|
||||
*/
|
||||
private String content;
|
||||
private String col = "0";
|
||||
/**
|
||||
* Cookie中的dy_did
|
||||
*/
|
||||
private String dy;
|
||||
/**
|
||||
* Cookie中的acf_uid
|
||||
*/
|
||||
private String sender;
|
||||
private String ifs = "0";
|
||||
private String nc = "0";
|
||||
private String dat = "0";
|
||||
private String rev = "0";
|
||||
/**
|
||||
* 当前时间戳(秒)
|
||||
*/
|
||||
private String tts;
|
||||
private String admzq = "0";
|
||||
/**
|
||||
* tts往后加几秒的时间戳(毫秒)
|
||||
*/
|
||||
private String cst;
|
||||
|
||||
public ChatmessageMsg(String content, String dy, String sender) {
|
||||
this.content = content;
|
||||
this.dy = dy;
|
||||
this.sender = sender;
|
||||
this.tts = String.valueOf(OrLocalDateTimeUtil.zonedCurrentTimeSecs());
|
||||
this.cst = String.valueOf(OrLocalDateTimeUtil.zonedCurrentTimeMillis() + RandomUtil.randomLong(8000, 10000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.chatmessage.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IDanmuMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "type": "chatmsg",
|
||||
* "cmdEnum": "chatmsg",
|
||||
* "cmd": "chatmsg",
|
||||
* "nn": "宋老二929",
|
||||
* "ext": null,
|
||||
* "bnn": null,
|
||||
* "level": "1",
|
||||
* "cst": "1693213418102",
|
||||
* "brid": "0",
|
||||
* "bl": "0",
|
||||
* "dms": "5",
|
||||
* "rid": "3168536",
|
||||
* "uid": "396023456",
|
||||
* "txt": "666",
|
||||
* "pdg": "47",
|
||||
* "pdk": "89",
|
||||
* "sahf": "0",
|
||||
* "ic": ["avatar_v3", "202101", "45daf5ceb475414293e3da4559552655"],
|
||||
* "hb": ["2719"],
|
||||
* "hc": null,
|
||||
* "cid": "0b37e26cccd54f7c4d73590000000000",
|
||||
* "lk": null
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/28
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ChatmsgMsg extends BaseDouyuCmdMsg implements IDanmuMsg {
|
||||
|
||||
private String nn;
|
||||
private String ext;
|
||||
private String bnn;
|
||||
private String level;
|
||||
private String cst;
|
||||
private String brid;
|
||||
private byte bl;
|
||||
private String dms;
|
||||
private long rid;
|
||||
private String uid;
|
||||
private String txt;
|
||||
private String pdg;
|
||||
private String pdk;
|
||||
private String sahf;
|
||||
private List<String> ic;
|
||||
private List<String> hb;
|
||||
private String hc;
|
||||
private String cid;
|
||||
private JsonNode lk;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.chatmsg.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBadgeName() {
|
||||
return this.bnn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getBadgeLevel() {
|
||||
return this.bl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.nn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserAvatar() {
|
||||
return DouyuApis.getSmallAvatarUrl(ic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContent() {
|
||||
return this.txt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IGiftMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftListInfo;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftPropSingle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 收到礼物消息
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "type": "dgb",
|
||||
* "nn": "用户名",
|
||||
* "eid": "0",
|
||||
* "bst": "32",
|
||||
* "brid": "0",
|
||||
* "pma": "186963537",
|
||||
* "bnid": "1",
|
||||
* "gfid": "824",
|
||||
* "bl": "0",
|
||||
* "pid": "268",
|
||||
* "rid": "290935",
|
||||
* "mss": "186963457",
|
||||
* "bcst": "2",
|
||||
* "uid": "用户id",
|
||||
* "receive_uid": "接受用户id",
|
||||
* "ic": ["avatar_v3", "201912", "d031765fbe764a49887083bcf200da0b"],
|
||||
* "from": "2",
|
||||
* "gpf": "1",
|
||||
* "bnl": "1",
|
||||
* "ce": "1",
|
||||
* "bnn": null,
|
||||
* "receive_nn": "接受用户用户名",
|
||||
* "level": "43",
|
||||
* "bcnt": "1",
|
||||
* "gs": "0",
|
||||
* "hits": "249",
|
||||
* "gfcnt": "249",
|
||||
* "ct": "0",
|
||||
* "pfm": "27585",
|
||||
* "sahf": "0",
|
||||
* "hc": null,
|
||||
* "fc": "0",
|
||||
* "eic": "0"
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DgbMsg extends BaseDouyuCmdMsg implements IGiftMsg {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String nn;
|
||||
private String eid;
|
||||
private String bst;
|
||||
private String brid;
|
||||
private String pma;
|
||||
private String bnid;
|
||||
private long gfid;
|
||||
private byte bl;
|
||||
private String pid;
|
||||
private String rid;
|
||||
private String mss;
|
||||
private String bcst;
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private String uid;
|
||||
/**
|
||||
* 收礼物用户id
|
||||
*/
|
||||
private long receive_uid;
|
||||
private List<String> ic;
|
||||
private String from;
|
||||
private String gpf;
|
||||
private String bnl;
|
||||
private String ce;
|
||||
private String bnn;
|
||||
/**
|
||||
* 收礼物用户名
|
||||
*/
|
||||
private String receive_nn;
|
||||
private String level;
|
||||
private String bcnt;
|
||||
private String gs;
|
||||
/**
|
||||
* 连击
|
||||
*/
|
||||
private String hits;
|
||||
/**
|
||||
* 礼物个数
|
||||
*/
|
||||
private int gfcnt;
|
||||
private String ct;
|
||||
private String pfm;
|
||||
private String sahf;
|
||||
private String hc;
|
||||
private String fc;
|
||||
private String eic;
|
||||
private String bsfl;
|
||||
private String skinid;
|
||||
|
||||
// region 额外属性
|
||||
private GiftPropSingle giftInfo = GiftPropSingle.DEFAULT_GIFT;
|
||||
private GiftListInfo roomGiftInfo = GiftListInfo.DEFAULT_GIFT;
|
||||
// endregion
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.dgb.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBadgeName() {
|
||||
return this.bnn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getBadgeLevel() {
|
||||
return this.bl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.nn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserAvatar() {
|
||||
return DouyuApis.getSmallAvatarUrl(ic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGiftName() {
|
||||
if (this.roomGiftInfo != null && this.roomGiftInfo != GiftListInfo.DEFAULT_GIFT) {
|
||||
return this.roomGiftInfo.getName();
|
||||
}
|
||||
|
||||
if (this.giftInfo == null) {
|
||||
return "未知礼物";
|
||||
}
|
||||
|
||||
return this.giftInfo.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGiftImg() {
|
||||
if (this.roomGiftInfo != null && this.roomGiftInfo != GiftListInfo.DEFAULT_GIFT && this.roomGiftInfo.getBasicInfo() != null) {
|
||||
return this.roomGiftInfo.getPicUrlPrefix() + this.roomGiftInfo.getBasicInfo().getChatPic();
|
||||
}
|
||||
|
||||
if (this.giftInfo == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return this.giftInfo.getPicUrlPrefix() + this.giftInfo.getChatPic();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGiftId() {
|
||||
return Long.toString(this.gfid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGiftCount() {
|
||||
return this.gfcnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 100 => 1鱼翅
|
||||
*/
|
||||
@Override
|
||||
public int getGiftPrice() {
|
||||
if (this.roomGiftInfo != null && this.roomGiftInfo != GiftListInfo.DEFAULT_GIFT && this.roomGiftInfo.getPriceInfo() != null) {
|
||||
return this.roomGiftInfo.getPriceInfo().getPrice();
|
||||
}
|
||||
|
||||
if (this.giftInfo == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.giftInfo.getPrice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReceiveUid() {
|
||||
return Long.toString(this.receive_uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReceiveUsername() {
|
||||
return this.receive_nn;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* type@=chatmsg/rid@=7750753/uid@=549977/nn@=一闪一闪亮品品/txt@=冷门歌手哎,声音独特哎/cid@=044c3bf3074b483275a44e0000000000/ic@=avatar@Sdefault@S08/level@=29/sahf@=0/nl@=7/cst@=1693107871294/bnn@=/bl@=0/brid@=0/hc@=/lk@=/dms@=8/pdg@=26/pdk@=86/ext@=/
|
||||
*
|
||||
* @see tech.ordinaryroad.live.chat.client.douyu.util.DouyuCodecUtil#getDouyuMsgClassByType(DouyuCmdEnum, short)
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DouyuCmdMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String tick;
|
||||
|
||||
private String res;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class H5ckreqMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String rid;
|
||||
private String ti;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.h5ckreq.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class H5csMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String result;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.h5cs.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class H5gkcreqMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String rid;
|
||||
private String ti;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.h5gkcreq.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
public class HeartbeatMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.mrkl.name();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
public class HeartbeatReplyMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.mrkl.name();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class JoingroupMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private long rid;
|
||||
private long gid = -9999;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.joingroup.name();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLocalDateTimeUtil;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* <pre>{@code
|
||||
* type@=keeplive/vbw@=0/cdn@=hs-h5/tick@=1694099389/kd@=da9c384371b4552ac94e1237d2596262/
|
||||
* }</pre>
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/9/7
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class KeepliveMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String vbw = "0";
|
||||
private String cnd;
|
||||
private long tick = OrLocalDateTimeUtil.zonedCurrentTimeSecs();
|
||||
private String kd = "";
|
||||
|
||||
public KeepliveMsg(String cnd) {
|
||||
this.cnd = cnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.keeplive.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLocalDateTimeUtil;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@RequiredArgsConstructor
|
||||
public class LoginreqMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
public static List<String> SHOULD_IGNORE_NEW_LOGIN_PROPERTIES = Arrays.asList("roomid", "dfl", "username", "uid", "ver", "aver", "ct", "type");
|
||||
public static List<String> SHOULD_IGNORE_OLD_LOGIN_PROPERTIES = Arrays.asList("type", "roomid", "dfl", "username", "password", "ltkid", "biz", "stk", "devid", "ct", "pt", "cvr", "tvr", "apd", "rt", "vk", "ver", "aver", "dmbt", "dmbv");
|
||||
|
||||
private long roomid;
|
||||
private String dfl;
|
||||
private String username;
|
||||
private long uid;
|
||||
private String ver;
|
||||
private String aver;
|
||||
private int ct = 0;
|
||||
|
||||
private String password;
|
||||
/**
|
||||
* Cookie中的acf_ltkid
|
||||
*/
|
||||
private String ltkid;
|
||||
private String biz;
|
||||
/**
|
||||
* Cookie中的acf_stk
|
||||
*/
|
||||
private String stk;
|
||||
/**
|
||||
* Cookie中的dy_did
|
||||
*/
|
||||
private String devid;
|
||||
private String pt = "2";
|
||||
private String cvr = "0";
|
||||
private String tvr = "7";
|
||||
private String apd = "";
|
||||
private long rt = OrLocalDateTimeUtil.zonedCurrentTimeSecs();
|
||||
private String vk;
|
||||
private String dmbt = "chrome";
|
||||
private String dmbv = "116";
|
||||
|
||||
public LoginreqMsg(long roomid, String dfl, String username, long uid, String ver, String aver) {
|
||||
this.roomid = roomid;
|
||||
this.dfl = dfl;
|
||||
this.username = username;
|
||||
this.uid = uid;
|
||||
this.ver = ver;
|
||||
this.aver = aver;
|
||||
}
|
||||
|
||||
public LoginreqMsg(long roomid, String dfl, String username, String ver, String aver, String ltkid, String biz, String stk, String devid) {
|
||||
this.roomid = roomid;
|
||||
this.dfl = dfl;
|
||||
this.username = username;
|
||||
this.ver = ver;
|
||||
this.aver = aver;
|
||||
this.ltkid = ltkid;
|
||||
this.biz = biz;
|
||||
this.stk = stk;
|
||||
this.devid = devid;
|
||||
this.vk = DouyuApis.generateVk(devid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.loginreq.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LoginresMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private long userid;
|
||||
private int roomgroup;
|
||||
private int pg;
|
||||
private long sessionid;
|
||||
private String username;
|
||||
private String nickname;
|
||||
private int live_stat;
|
||||
private boolean is_illegal;
|
||||
private String ill_ct;
|
||||
private String ill_ts;
|
||||
private String now;
|
||||
private String ps;
|
||||
private String es;
|
||||
private String it;
|
||||
private String its;
|
||||
private String npv;
|
||||
private String best_dlev;
|
||||
private String cur_lev;
|
||||
private String nrc;
|
||||
private String ih;
|
||||
private String sid;
|
||||
private String sahf;
|
||||
private String sceneid;
|
||||
private String newrg;
|
||||
private String regts;
|
||||
private String ip;
|
||||
private String rn;
|
||||
private String rct;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.loginres.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/28
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MapkbMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private long pk_time;
|
||||
private List<Object> teams;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.mapkb.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MsgrepeaterproxylistMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String rid;
|
||||
|
||||
/**
|
||||
* <pre>{@code
|
||||
* [{
|
||||
* "nr": "0",
|
||||
* "port": "8501",
|
||||
* "ip": "danmuproxy.douyu.com",
|
||||
* "id": "0",
|
||||
* "ml": "10000"
|
||||
* }, {
|
||||
* "nr": "0",
|
||||
* "port": "8502",
|
||||
* "ip": "danmuproxy.douyu.com",
|
||||
* "id": "0",
|
||||
* "ml": "10000"
|
||||
* }, {
|
||||
* "nr": "0",
|
||||
* "port": "8503",
|
||||
* "ip": "danmuproxy.douyu.com",
|
||||
* "id": "0",
|
||||
* "ml": "10000"
|
||||
* }, {
|
||||
* "nr": "0",
|
||||
* "port": "8504",
|
||||
* "ip": "danmuproxy.douyu.com",
|
||||
* "id": "0",
|
||||
* "ml": "10000"
|
||||
* }, {
|
||||
* "nr": "0",
|
||||
* "port": "8505",
|
||||
* "ip": "danmuproxy.douyu.com",
|
||||
* "id": "0",
|
||||
* "ml": "10000"
|
||||
* }, {
|
||||
* "nr": "0",
|
||||
* "port": "8506",
|
||||
* "ip": "danmuproxy.douyu.com",
|
||||
* "id": "0",
|
||||
* "ml": "10000"
|
||||
* }]
|
||||
* }</pre>
|
||||
*/
|
||||
private List<Map<String, String>> list;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.msgrepeaterproxylist.name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SubMsg extends BaseDouyuCmdMsg {
|
||||
|
||||
private String mt = "dayrk";
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return DouyuCmdEnum.sub.name();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IEnterRoomMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/12/27
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UenterMsg extends BaseDouyuCmdMsg implements IEnterRoomMsg {
|
||||
|
||||
private String nn;
|
||||
private long uid;
|
||||
private int level;
|
||||
private String sahf;
|
||||
private List<String> ic;
|
||||
private String rid;
|
||||
|
||||
@Override
|
||||
public String getBadgeName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getBadgeLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUid() {
|
||||
return Long.toString(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return nn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserAvatar() {
|
||||
return DouyuApis.getSmallAvatarUrl(ic);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg.base;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public abstract class BaseDouyuCmdMsg extends BaseCmdMsg<DouyuCmdEnum> implements IDouyuMsg {
|
||||
|
||||
private String type;
|
||||
|
||||
@Override
|
||||
public String getCmd() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCmd(String cmd) {
|
||||
type = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DouyuCmdEnum getCmdEnum() {
|
||||
return DouyuCmdEnum.getByString(type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg.base;
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public interface IDouyuMsg extends IMsg {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GiftListInfo {
|
||||
|
||||
public static final GiftListInfo DEFAULT_GIFT = new GiftListInfo();
|
||||
|
||||
private BasicInfo basicInfo;
|
||||
private JsonNode batchInfo;
|
||||
private int batchInfoFlag;
|
||||
private int countLimit;
|
||||
private int defaultSkinId;
|
||||
private int donateStatus;
|
||||
private JsonNode effectInfo;
|
||||
private int effectStatus;
|
||||
private int endTime;
|
||||
private JsonNode growthInfo;
|
||||
private long hitInterval;
|
||||
private int id;
|
||||
private int isBatchLimited;
|
||||
private int isFace;
|
||||
private String name = "未知礼物";
|
||||
private String picUrlPrefix;
|
||||
private PriceInfo priceInfo = new PriceInfo();
|
||||
private int showStatus;
|
||||
private List<String> skinIds;
|
||||
private int startTime;
|
||||
private List<Integer> tabIds;
|
||||
|
||||
/**
|
||||
* 未知属性都放在这
|
||||
*/
|
||||
private final Map<String, JsonNode> unknownProperties = new HashMap<>();
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, JsonNode> getUnknownProperties() {
|
||||
return unknownProperties;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public void setOther(String key, JsonNode value) {
|
||||
this.unknownProperties.put(key, value);
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class BasicInfo {
|
||||
private String bizTag;
|
||||
private String borderColor;
|
||||
private String chatPic;
|
||||
private String culture;
|
||||
private String desc1;
|
||||
private String desc2;
|
||||
private String focusPic;
|
||||
private String giftPic;
|
||||
private int giftType;
|
||||
private int guardLevel;
|
||||
private String sendPic;
|
||||
private String subscriptColor;
|
||||
private String subscriptText;
|
||||
private String webSubscriptBigPic;
|
||||
private String webSubscriptSmallPic;
|
||||
private String webSubscriptText;
|
||||
|
||||
/**
|
||||
* 未知属性都放在这
|
||||
*/
|
||||
private final Map<String, JsonNode> unknownProperties = new HashMap<>();
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, JsonNode> getUnknownProperties() {
|
||||
return unknownProperties;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public void setOther(String key, JsonNode value) {
|
||||
this.unknownProperties.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class PriceInfo {
|
||||
private int price = -1;
|
||||
private String priceType;
|
||||
private int returnNum;
|
||||
|
||||
/**
|
||||
* 未知属性都放在这
|
||||
*/
|
||||
private final Map<String, JsonNode> unknownProperties = new HashMap<>();
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, JsonNode> getUnknownProperties() {
|
||||
return unknownProperties;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public void setOther(String key, JsonNode value) {
|
||||
this.unknownProperties.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GiftPropInfo {
|
||||
|
||||
public static final GiftPropInfo DEFAULT_GIFT = new GiftPropInfo();
|
||||
|
||||
private String name = "未知礼物";
|
||||
private String bimg;
|
||||
private String himg;
|
||||
private String cimg;
|
||||
private int stay_time;
|
||||
private int show_combo;
|
||||
private String batch_preset;
|
||||
private List<String> hit;
|
||||
private int type;
|
||||
private int style;
|
||||
private int pc;
|
||||
private int ry;
|
||||
private int ef;
|
||||
private int effect;
|
||||
private int is_syn_fs;
|
||||
private int is_stay;
|
||||
private String drgb;
|
||||
private String urgb;
|
||||
private String grgb;
|
||||
private String brgb;
|
||||
private String small_effect_icon;
|
||||
private String big_effect_icon;
|
||||
private String effect_icon;
|
||||
private String gift_icon;
|
||||
private String gift_open_icon;
|
||||
private int bonus;
|
||||
private String web_flash;
|
||||
private String hit_interval;
|
||||
private int devote;
|
||||
private int attack;
|
||||
private int exp;
|
||||
private int active_type;
|
||||
private String pc_full_icon;
|
||||
private String pc_full_bg_icon;
|
||||
private int pc_show_combo;
|
||||
private String pc_urgb;
|
||||
private String pc_grgb;
|
||||
private int index;
|
||||
|
||||
/**
|
||||
* 未知属性都放在这
|
||||
*/
|
||||
private final Map<String, JsonNode> unknownProperties = new HashMap<>();
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, JsonNode> getUnknownProperties() {
|
||||
return unknownProperties;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public void setOther(String key, JsonNode value) {
|
||||
this.unknownProperties.put(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package tech.ordinaryroad.live.chat.client.douyu.msg.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GiftPropSingle {
|
||||
|
||||
public static final GiftPropSingle DEFAULT_GIFT = new GiftPropSingle();
|
||||
|
||||
// key,value
|
||||
private JsonNode batchInfo;
|
||||
private String bizTag;
|
||||
private String borderColor;
|
||||
private String chatPic;
|
||||
private int count;
|
||||
private String description;
|
||||
private String description2;
|
||||
private int devote;
|
||||
// key,value
|
||||
private JsonNode effectInfo;
|
||||
private int exp;
|
||||
private int expiry;
|
||||
private String focusPic;
|
||||
private int hitInterval;
|
||||
private long id;
|
||||
private int intimate;
|
||||
private String intro;
|
||||
private int isClick;
|
||||
private int isFace;
|
||||
private int isValuable;
|
||||
private int level;
|
||||
private int levelTime;
|
||||
private int met;
|
||||
private String name = "未知礼物";
|
||||
private String picUrlPrefix;
|
||||
private int price = -1;
|
||||
private int priceType;
|
||||
private String propPic;
|
||||
private int propType;
|
||||
private int returnNum;
|
||||
private String sendPic;
|
||||
private String subscriptColor;
|
||||
private String subscriptText;
|
||||
private String webSubscriptBigPic;
|
||||
private String webSubscriptSmallPic;
|
||||
private String webSubscriptText;
|
||||
|
||||
/**
|
||||
* 未知属性都放在这
|
||||
*/
|
||||
private final Map<String, JsonNode> unknownProperties = new HashMap<>();
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, JsonNode> getUnknownProperties() {
|
||||
return unknownProperties;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public void setOther(String key, JsonNode value) {
|
||||
this.unknownProperties.put(key, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.netty.frame;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.base.BaseDouyuWebSocketFrame;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
public class AuthWebSocketFrame extends BaseDouyuWebSocketFrame {
|
||||
|
||||
public AuthWebSocketFrame(ByteBuf byteBuf) {
|
||||
super(byteBuf);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.netty.frame;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.base.BaseDouyuWebSocketFrame;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
public class HeartbeatWebSocketFrame extends BaseDouyuWebSocketFrame {
|
||||
|
||||
public HeartbeatWebSocketFrame(ByteBuf byteBuf) {
|
||||
super(byteBuf);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.netty.frame;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.base.BaseDouyuWebSocketFrame;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
public class KeepliveWebSocketFrame extends BaseDouyuWebSocketFrame {
|
||||
|
||||
public KeepliveWebSocketFrame(ByteBuf byteBuf) {
|
||||
super(byteBuf);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.netty.frame.base;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
public abstract class BaseDouyuWebSocketFrame extends BinaryWebSocketFrame {
|
||||
|
||||
public BaseDouyuWebSocketFrame(ByteBuf byteBuf) {
|
||||
super(byteBuf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.netty.frame.factory;
|
||||
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLiveChatCookieUtil;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.config.DouyuLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuClientModeEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.*;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.AuthWebSocketFrame;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.HeartbeatWebSocketFrame;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.KeepliveWebSocketFrame;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.util.DouyuCodecUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
public class DouyuWebSocketFrameFactory {
|
||||
|
||||
private static final ConcurrentHashMap<Long, DouyuWebSocketFrameFactory> CACHE = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* 浏览器地址中的房间id,暂不支持短id
|
||||
*/
|
||||
private final long roomId;
|
||||
private volatile static HeartbeatMsg heartbeatMsg;
|
||||
|
||||
public DouyuWebSocketFrameFactory(long roomId) {
|
||||
this.roomId = roomId;
|
||||
}
|
||||
|
||||
public synchronized static DouyuWebSocketFrameFactory getInstance(long roomId) {
|
||||
return CACHE.computeIfAbsent(roomId, aLong -> new DouyuWebSocketFrameFactory(roomId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建认证包
|
||||
*
|
||||
* @param mode {@link DouyuClientModeEnum#DANMU}, {@link DouyuClientModeEnum#WS}
|
||||
* @param ver {@link DouyuLiveChatClientConfig#getVer()}
|
||||
* @param aver {@link DouyuLiveChatClientConfig#getAver()}
|
||||
* @param cookie 浏览器Cookie,发送弹幕时必传
|
||||
* @return AuthWebSocketFrame
|
||||
*/
|
||||
public AuthWebSocketFrame createAuth(DouyuClientModeEnum mode, String ver, String aver, String cookie) {
|
||||
try {
|
||||
// type@=loginreq/roomid@=7750753/dfl@=/username@=visitor10424697/uid@=1168052601/ver@=20220825/aver@=218101901/ct@=0/
|
||||
LoginreqMsg loginreqMsg;
|
||||
long realRoomId = DouyuApis.getRealRoomId(roomId);
|
||||
long uid;
|
||||
String username;
|
||||
Map<String, String> cookieMap = OrLiveChatCookieUtil.parseCookieString(cookie);
|
||||
|
||||
if (cookieMap.isEmpty()) {
|
||||
// 视为未登录
|
||||
if (mode == DouyuClientModeEnum.DANMU) {
|
||||
uid = RandomUtil.randomLong(10000000, 19999999);
|
||||
username = "visitor" + RandomUtil.randomLong(10000000, 19999999);
|
||||
loginreqMsg = new LoginreqMsg(realRoomId, "", username, uid, ver, aver);
|
||||
return new AuthWebSocketFrame(DouyuCodecUtil.encode(loginreqMsg, LoginreqMsg.SHOULD_IGNORE_NEW_LOGIN_PROPERTIES));
|
||||
} else {
|
||||
loginreqMsg = new LoginreqMsg(realRoomId, "", "", ver, aver, "", "", "", UUID.fastUUID().toString(true));
|
||||
return new AuthWebSocketFrame(DouyuCodecUtil.encode(loginreqMsg, LoginreqMsg.SHOULD_IGNORE_OLD_LOGIN_PROPERTIES));
|
||||
}
|
||||
}
|
||||
// 视为登录
|
||||
else {
|
||||
String acfUid = OrLiveChatCookieUtil.getCookieByName(cookieMap, DouyuApis.KEY_COOKIE_ACF_UID, () -> {
|
||||
throw new BaseException("Cookie中缺少字段" + DouyuApis.KEY_COOKIE_ACF_UID);
|
||||
});
|
||||
uid = NumberUtil.parseLong(acfUid);
|
||||
username = acfUid;
|
||||
String dfl = "sn@A=105@Sss@A=1";
|
||||
if (mode == DouyuClientModeEnum.DANMU) {
|
||||
loginreqMsg = new LoginreqMsg(realRoomId, dfl, username, uid, ver, aver);
|
||||
return new AuthWebSocketFrame(DouyuCodecUtil.encode(loginreqMsg, LoginreqMsg.SHOULD_IGNORE_NEW_LOGIN_PROPERTIES));
|
||||
} else {
|
||||
String acfLtkid = OrLiveChatCookieUtil.getCookieByName(cookieMap, DouyuApis.KEY_COOKIE_ACF_LTKID, () -> {
|
||||
throw new BaseException("Cookie中缺少字段" + DouyuApis.KEY_COOKIE_ACF_LTKID);
|
||||
});
|
||||
String acfStk = OrLiveChatCookieUtil.getCookieByName(cookieMap, DouyuApis.KEY_COOKIE_ACF_STK, () -> {
|
||||
throw new BaseException("Cookie中缺少字段" + DouyuApis.KEY_COOKIE_ACF_STK);
|
||||
});
|
||||
String dyDid = OrLiveChatCookieUtil.getCookieByName(cookieMap, DouyuApis.KEY_COOKIE_DY_DID, () -> {
|
||||
throw new BaseException("Cookie中缺少字段" + DouyuApis.KEY_COOKIE_DY_DID);
|
||||
});
|
||||
loginreqMsg = new LoginreqMsg(realRoomId, dfl, username, ver, aver, acfLtkid, "1", acfStk, dyDid);
|
||||
return new AuthWebSocketFrame(DouyuCodecUtil.encode(loginreqMsg, LoginreqMsg.SHOULD_IGNORE_OLD_LOGIN_PROPERTIES));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new BaseException(String.format("认证包创建失败,请检查房间号是否正确。roomId: %d, msg: %s", roomId, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public AuthWebSocketFrame createAuth(DouyuClientModeEnum mode, String ver, String aver) {
|
||||
return this.createAuth(mode, ver, aver, null);
|
||||
}
|
||||
|
||||
public HeartbeatWebSocketFrame createHeartbeat() {
|
||||
return new HeartbeatWebSocketFrame(DouyuCodecUtil.encode(this.getHeartbeatMsg()));
|
||||
}
|
||||
|
||||
public KeepliveWebSocketFrame createKeeplive(String cookie) {
|
||||
return new KeepliveWebSocketFrame(DouyuCodecUtil.encode(this.getKeepliveMsg(StrUtil.isNotBlank(cookie) ? "hs-h5" : "")));
|
||||
}
|
||||
|
||||
/**
|
||||
* 心跳包单例模式
|
||||
*
|
||||
* @return HeartbeatWebSocketFrame
|
||||
*/
|
||||
public HeartbeatMsg getHeartbeatMsg() {
|
||||
if (heartbeatMsg == null) {
|
||||
synchronized (DouyuWebSocketFrameFactory.this) {
|
||||
if (heartbeatMsg == null) {
|
||||
heartbeatMsg = new HeartbeatMsg();
|
||||
}
|
||||
}
|
||||
}
|
||||
return heartbeatMsg;
|
||||
}
|
||||
|
||||
private BaseDouyuCmdMsg getKeepliveMsg(String cnd) {
|
||||
return new KeepliveMsg(cnd);
|
||||
}
|
||||
|
||||
public WebSocketFrame createJoingroup() {
|
||||
JoingroupMsg joingroupMsg = new JoingroupMsg();
|
||||
joingroupMsg.setRid(roomId);
|
||||
return new BinaryWebSocketFrame(DouyuCodecUtil.encode(joingroupMsg));
|
||||
}
|
||||
|
||||
public WebSocketFrame createSub() {
|
||||
return new BinaryWebSocketFrame(DouyuCodecUtil.encode(new SubMsg()));
|
||||
}
|
||||
|
||||
public WebSocketFrame createDanmu(String msg, String cookie) {
|
||||
String dyDid = OrLiveChatCookieUtil.getCookieByName(cookie, DouyuApis.KEY_COOKIE_DY_DID, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + DouyuApis.KEY_COOKIE_DY_DID);
|
||||
});
|
||||
String acfUid = OrLiveChatCookieUtil.getCookieByName(cookie, DouyuApis.KEY_COOKIE_ACF_UID, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + DouyuApis.KEY_COOKIE_ACF_UID);
|
||||
});
|
||||
ChatmessageMsg chatmessageMsg = new ChatmessageMsg(msg, dyDid, acfUid);
|
||||
return new BinaryWebSocketFrame(DouyuCodecUtil.encode(chatmessageMsg));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.netty.handler;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.ICmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.client.base.BaseDouyuLiveChatClient;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.ChatmsgMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.DgbMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.DouyuCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.UenterMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.IDouyuMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.util.DouyuCodecUtil;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.handler.BaseNettyClientBinaryFrameHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 消息处理器
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/1/4
|
||||
*/
|
||||
@Slf4j
|
||||
@ChannelHandler.Sharable
|
||||
public class DouyuBinaryFrameHandler extends BaseNettyClientBinaryFrameHandler<BaseDouyuLiveChatClient, DouyuBinaryFrameHandler, DouyuCmdEnum, IDouyuMsg, IDouyuMsgListener> {
|
||||
|
||||
public DouyuBinaryFrameHandler(List<IDouyuMsgListener> msgListeners, BaseDouyuLiveChatClient client) {
|
||||
super(msgListeners, client);
|
||||
}
|
||||
|
||||
public DouyuBinaryFrameHandler(List<IDouyuMsgListener> msgListeners, long roomId) {
|
||||
super(msgListeners, roomId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCmdMsg(DouyuCmdEnum cmd, ICmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
if (super.msgListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case chatmsg: {
|
||||
iteratorMsgListeners(msgListener -> msgListener.onDanmuMsg(DouyuBinaryFrameHandler.this, (ChatmsgMsg) cmdMsg));
|
||||
break;
|
||||
}
|
||||
case dgb: {
|
||||
iteratorMsgListeners(msgListener -> msgListener.onGiftMsg(DouyuBinaryFrameHandler.this, (DgbMsg) cmdMsg));
|
||||
break;
|
||||
}
|
||||
case uenter: {
|
||||
iteratorMsgListeners(msgListener -> msgListener.onEnterRoomMsg(DouyuBinaryFrameHandler.this, (UenterMsg) cmdMsg));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (!(cmdMsg instanceof DouyuCmdMsg)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("非DouyuCmdMsg {}", cmdMsg.getClass());
|
||||
}
|
||||
return;
|
||||
}
|
||||
iteratorMsgListeners(msgListener -> msgListener.onOtherCmdMsg(DouyuBinaryFrameHandler.this, cmd, cmdMsg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<IDouyuMsg> decode(ByteBuf byteBuf) {
|
||||
return DouyuCodecUtil.decode(byteBuf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.netty.handler;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.client.base.BaseDouyuLiveChatClient;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.config.DouyuLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuClientModeEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.frame.factory.DouyuWebSocketFrameFactory;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.handler.BaseNettyClientConnectionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* 连接处理器
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
@Slf4j
|
||||
@ChannelHandler.Sharable
|
||||
public class DouyuConnectionHandler extends BaseNettyClientConnectionHandler<BaseDouyuLiveChatClient, DouyuConnectionHandler> {
|
||||
|
||||
@Getter
|
||||
private final DouyuClientModeEnum mode;
|
||||
/**
|
||||
* 以ClientConfig为主
|
||||
*/
|
||||
private final long roomId;
|
||||
/**
|
||||
* 以ClientConfig为主
|
||||
*/
|
||||
private final String ver;
|
||||
/**
|
||||
* 以ClientConfig为主
|
||||
*/
|
||||
private final String aver;
|
||||
/**
|
||||
* 以ClientConfig为主
|
||||
*/
|
||||
private String cookie;
|
||||
|
||||
public DouyuConnectionHandler(DouyuClientModeEnum mode, WebSocketClientHandshaker handshaker, BaseDouyuLiveChatClient client, IBaseConnectionListener<DouyuConnectionHandler> listener) {
|
||||
super(handshaker, client, listener);
|
||||
this.mode = mode;
|
||||
this.roomId = client.getConfig().getRoomId();
|
||||
this.ver = client.getConfig().getVer();
|
||||
this.aver = client.getConfig().getAver();
|
||||
this.cookie = client.getConfig().getCookie();
|
||||
}
|
||||
|
||||
public DouyuConnectionHandler(DouyuClientModeEnum mode, WebSocketClientHandshaker handshaker, BaseDouyuLiveChatClient client) {
|
||||
this(mode, handshaker, client, null);
|
||||
}
|
||||
|
||||
public DouyuConnectionHandler(DouyuClientModeEnum mode, WebSocketClientHandshaker handshaker, long roomId, String ver, String aver, IBaseConnectionListener<DouyuConnectionHandler> listener, String cookie) {
|
||||
super(handshaker, listener);
|
||||
this.mode = mode;
|
||||
this.roomId = roomId;
|
||||
this.ver = ver;
|
||||
this.aver = aver;
|
||||
this.cookie = cookie;
|
||||
}
|
||||
|
||||
public DouyuConnectionHandler(DouyuClientModeEnum mode, WebSocketClientHandshaker handshaker, long roomId, String ver, String aver, IBaseConnectionListener<DouyuConnectionHandler> listener) {
|
||||
this(mode, handshaker, roomId, ver, aver, listener, null);
|
||||
}
|
||||
|
||||
public DouyuConnectionHandler(DouyuClientModeEnum mode, WebSocketClientHandshaker handshaker, long roomId, String ver, String aver, String cookie) {
|
||||
this(mode, handshaker, roomId, ver, aver, null, cookie);
|
||||
}
|
||||
|
||||
public DouyuConnectionHandler(DouyuClientModeEnum mode, WebSocketClientHandshaker handshaker, long roomId, String ver, String aver) {
|
||||
this(mode, handshaker, roomId, ver, aver, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendHeartbeat(ChannelHandlerContext ctx) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("发送心跳包");
|
||||
}
|
||||
WebSocketFrame webSocketFrame;
|
||||
if (mode == DouyuClientModeEnum.DANMU) {
|
||||
webSocketFrame = getWebSocketFrameFactory(getRoomId()).createHeartbeat();
|
||||
} else {
|
||||
webSocketFrame = getWebSocketFrameFactory(getRoomId()).createKeeplive(getCookie());
|
||||
}
|
||||
ctx.writeAndFlush(webSocketFrame).addListener((ChannelFutureListener) future -> {
|
||||
if (future.isSuccess()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("心跳包发送完成");
|
||||
}
|
||||
} else {
|
||||
log.error("心跳包发送失败", future.cause());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAuthRequest(Channel channel) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("发送认证包");
|
||||
}
|
||||
channel.writeAndFlush(getWebSocketFrameFactory(getRoomId()).createAuth(mode, getVer(), getAver(), getCookie()));
|
||||
}
|
||||
|
||||
private DouyuWebSocketFrameFactory getWebSocketFrameFactory(long roomId) {
|
||||
return DouyuWebSocketFrameFactory.getInstance(roomId);
|
||||
}
|
||||
|
||||
public long getRoomId() {
|
||||
return client != null ? client.getConfig().getRoomId() : roomId;
|
||||
}
|
||||
|
||||
private String getVer() {
|
||||
return client != null ? client.getConfig().getVer() : ver;
|
||||
}
|
||||
|
||||
private String getAver() {
|
||||
return client != null ? client.getConfig().getAver() : aver;
|
||||
}
|
||||
|
||||
private String getCookie() {
|
||||
return client != null ? client.getConfig().getCookie() : cookie;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getHeartbeatPeriod() {
|
||||
if (client == null) {
|
||||
return DouyuLiveChatClientConfig.DEFAULT_HEARTBEAT_PERIOD;
|
||||
} else {
|
||||
return client.getConfig().getHeartbeatPeriod();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getHeartbeatInitialDelay() {
|
||||
if (client == null) {
|
||||
return DouyuLiveChatClientConfig.DEFAULT_HEARTBEAT_INITIAL_DELAY;
|
||||
} else {
|
||||
return client.getConfig().getHeartbeatInitialDelay();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLiveChatReflectUtil;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.api.DouyuApis;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.client.DouyuLiveChatClient;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.DgbMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.DouyuCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.HeartbeatMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.HeartbeatReplyMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.IDouyuMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftListInfo;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftPropSingle;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 参考:https://open.douyu.com/source/api/63
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Slf4j
|
||||
public class DouyuCodecUtil {
|
||||
|
||||
public static final String[] IGNORE_PROPERTIES = {"OBJECT_MAPPER", "unknownProperties"};
|
||||
/**
|
||||
* 以SHOULD_IGNORE开头的成员变量将不会序列化
|
||||
*/
|
||||
public static final String SHOULD_IGNORE_PROPERTIES_PREFIX = "SHOULD_IGNORE";
|
||||
|
||||
public static final short MSG_TYPE_SEND = 689;
|
||||
public static final short MSG_TYPE_RECEIVE = 690;
|
||||
public static final short FRAME_HEADER_LENGTH = 8;
|
||||
|
||||
public static ByteBuf encode(BaseDouyuCmdMsg msg, List<String> containProperties) {
|
||||
ByteBuf out = Unpooled.buffer(FRAME_HEADER_LENGTH);
|
||||
String bodyDouyuSttString = StrUtil.nullToEmpty(toDouyuSttString(msg, containProperties)) + SUFFIX;
|
||||
byte[] bodyBytes = bodyDouyuSttString.getBytes(StandardCharsets.UTF_8);
|
||||
int length = bodyBytes.length + FRAME_HEADER_LENGTH;
|
||||
out.writeIntLE(length);
|
||||
out.writeIntLE(length);
|
||||
out.writeShortLE(MSG_TYPE_SEND);
|
||||
out.writeByte(0);
|
||||
out.writeByte(0);
|
||||
out.writeBytes(bodyBytes);
|
||||
return out;
|
||||
}
|
||||
|
||||
public static ByteBuf encode(BaseDouyuCmdMsg msg) {
|
||||
return encode(msg, null);
|
||||
}
|
||||
|
||||
public static List<IDouyuMsg> decode(ByteBuf in) {
|
||||
List<IDouyuMsg> msgList = new ArrayList<>();
|
||||
Queue<ByteBuf> pendingByteBuf = new LinkedList<>();
|
||||
|
||||
do {
|
||||
Optional<IDouyuMsg> msg = doDecode(in, pendingByteBuf);
|
||||
msg.ifPresent(msgList::add);
|
||||
in = pendingByteBuf.poll();
|
||||
} while (in != null);
|
||||
|
||||
return msgList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行解码操作
|
||||
*
|
||||
* @param in handler收到的一条消息
|
||||
* @param pendingByteBuf 用于存放未读取完的ByteBuf
|
||||
* @return Optional<IDouyuMsg> 何时为空值:不支持的{@link DouyuCmdEnum},{@link #parseDouyuSttString(String, short)}反序列化失败
|
||||
*/
|
||||
private static Optional<IDouyuMsg> doDecode(ByteBuf in, Queue<ByteBuf> pendingByteBuf) {
|
||||
int length = in.readIntLE();
|
||||
in.readIntLE();
|
||||
// MSG_TYPE_RECEIVE
|
||||
short msgType = in.readShortLE();
|
||||
if (msgType != MSG_TYPE_RECEIVE) {
|
||||
log.error("decode消息类型 非 收到的消息");
|
||||
}
|
||||
in.readByte();
|
||||
in.readByte();
|
||||
int contentLength = length - FRAME_HEADER_LENGTH;
|
||||
byte[] inputBytes = new byte[contentLength];
|
||||
in.readBytes(inputBytes);
|
||||
if (in.readableBytes() != 0) {
|
||||
// log.error("in.readableBytes() {}", in.readableBytes());
|
||||
pendingByteBuf.offer(in);
|
||||
}
|
||||
|
||||
String bodyDouyuSttString = new String(inputBytes, 0, inputBytes.length - 1);
|
||||
return Optional.ofNullable(parseDouyuSttString(bodyDouyuSttString, msgType));
|
||||
}
|
||||
|
||||
public static final String SPLITTER = "@=";
|
||||
public static final String END = "/";
|
||||
public static final String SUFFIX = "\0";
|
||||
|
||||
/**
|
||||
* <pre>{@code @S/ -> @AS@S}</pre>
|
||||
*
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
public static String escape(String string) {
|
||||
// return string == null ? StrUtil.EMPTY : (string.replaceAll("/", "@S").replaceAll("@", "@A"));
|
||||
return string == null ? StrUtil.EMPTY : (string.replaceAll("@", "@A").replaceAll("/", "@S"));
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>{@code @AS@S -> @S/}</pre>
|
||||
*
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
public static String unescape(String string) {
|
||||
return string == null ? StrUtil.EMPTY : (string.replaceAll("@S", "/").replaceAll("@A", "@"));
|
||||
}
|
||||
|
||||
public static String toDouyuSttString(Object object, List<String> containProperties) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (object instanceof IDouyuMsg) {
|
||||
Class<?> objectClass = object.getClass();
|
||||
Field[] fields = ReflectUtil.getFields(objectClass, field -> {
|
||||
String name = field.getName();
|
||||
if (CollUtil.isNotEmpty(containProperties)) {
|
||||
return containProperties.contains(name);
|
||||
} else {
|
||||
return !name.startsWith(SHOULD_IGNORE_PROPERTIES_PREFIX) && !ArrayUtil.contains(IGNORE_PROPERTIES, name);
|
||||
}
|
||||
});
|
||||
for (Field field : fields) {
|
||||
String key = field.getName();
|
||||
Method method = OrLiveChatReflectUtil.getGetterMethod(objectClass, key);
|
||||
Object value = ReflectUtil.invoke(object, method);
|
||||
String douyuSttString = toDouyuSttString(value, containProperties);
|
||||
String escape = escape(douyuSttString);
|
||||
sb.append(escape(key))
|
||||
.append(SPLITTER)
|
||||
.append(escape)
|
||||
.append(END);
|
||||
}
|
||||
} else {
|
||||
if (object instanceof Iterable<?>) {
|
||||
Iterable<?> iterable = (Iterable<?>) object;
|
||||
StringBuffer iterableStringBuffer = new StringBuffer();
|
||||
for (Object o : iterable) {
|
||||
String douyuSttString = toDouyuSttString(o, containProperties);
|
||||
String escape = escape(douyuSttString);
|
||||
iterableStringBuffer.append(escape)
|
||||
.append(END);
|
||||
}
|
||||
sb.append((iterableStringBuffer.toString()));
|
||||
} else if (object instanceof Map<?, ?>) {
|
||||
Map<?, ?> map = (Map<?, ?>) object;
|
||||
StringBuffer mapStringBuffer = new StringBuffer();
|
||||
map.forEach((mapKey, mapValue) -> {
|
||||
mapStringBuffer.append(escape(StrUtil.toStringOrNull(mapKey)))
|
||||
.append(SPLITTER)
|
||||
.append(escape(toDouyuSttString(mapValue, containProperties)))
|
||||
.append(END);
|
||||
});
|
||||
sb.append((mapStringBuffer.toString()));
|
||||
} else {
|
||||
sb.append((StrUtil.nullToEmpty(StrUtil.toStringOrNull(object))));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String toDouyuSttString(Object object) {
|
||||
return toDouyuSttString(object, null);
|
||||
}
|
||||
|
||||
public static IDouyuMsg parseDouyuSttString(String string, short msgType) {
|
||||
Map<String, Object> stringObjectMap = parseDouyuSttStringToMap(string);
|
||||
String type = (String) stringObjectMap.get("type");
|
||||
DouyuCmdEnum cmdEnum = DouyuCmdEnum.getByString(type);
|
||||
|
||||
Class<IDouyuMsg> msgClass = getDouyuMsgClassByType(cmdEnum, msgType);
|
||||
if (msgClass == null) {
|
||||
// TODO 不支持的cmdEnum
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("暂不支持 cmdEnum {}, msgType {}", cmdEnum, msgType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
IDouyuMsg t = ReflectUtil.newInstance(msgClass);
|
||||
stringObjectMap.forEach((key, value) -> {
|
||||
Field field = ReflectUtil.getField(t.getClass(), key);
|
||||
// 未知key
|
||||
if (field == null) {
|
||||
// Object -> JsonNode
|
||||
((BaseDouyuCmdMsg) t).getUnknownProperties().put(key, BaseDouyuCmdMsg.OBJECT_MAPPER.valueToTree(value));
|
||||
// log.debug("未知key {} {},已存放于unknownProperties中", msgClass, key);
|
||||
} else {
|
||||
ReflectUtil.setFieldValue(t, field, value);
|
||||
}
|
||||
});
|
||||
|
||||
// 礼物消息设置礼物信息字段
|
||||
if (t instanceof DgbMsg) {
|
||||
DgbMsg msg = (DgbMsg) t;
|
||||
String pid = msg.getPid();
|
||||
// 通用礼物
|
||||
if (StrUtil.isNotBlank(pid)) {
|
||||
GiftPropSingle giftSingle = DouyuLiveChatClient.giftMap.get(pid, () -> {
|
||||
GiftPropSingle gift = GiftPropSingle.DEFAULT_GIFT;
|
||||
try {
|
||||
gift = DouyuApis.getGiftPropSingleByPid(pid);
|
||||
} catch (Exception e) {
|
||||
log.error("礼物信息获取失败, pid=" + pid, e);
|
||||
}
|
||||
return gift;
|
||||
});
|
||||
msg.setGiftInfo(giftSingle);
|
||||
}
|
||||
// 房间礼物
|
||||
else {
|
||||
String realRoomId = msg.getRid();
|
||||
if (DouyuLiveChatClient.roomGiftMap.containsKey(realRoomId)) {
|
||||
Map<String, GiftListInfo> stringGiftListInfoMap = DouyuLiveChatClient.roomGiftMap.get(realRoomId);
|
||||
msg.setRoomGiftInfo(stringGiftListInfoMap.getOrDefault(String.valueOf(msg.getGfid()), GiftListInfo.DEFAULT_GIFT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Object parseDouyuSttStringToObject(String value) {
|
||||
Object valueObject;
|
||||
if (StrUtil.isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
if (value.contains(SPLITTER) && value.contains(END)) {
|
||||
// log.debug("map valueObject {}", value);
|
||||
valueObject = parseDouyuSttStringToMap(value);
|
||||
}
|
||||
// List<Object>
|
||||
else if (!value.contains(SPLITTER) && value.contains(END)) {
|
||||
// log.debug("list valueObject {}", value);
|
||||
List<Object> list = new ArrayList<>();
|
||||
for (String s : value.split(END)) {
|
||||
list.add(parseDouyuSttStringToObject(unescape(s)));
|
||||
}
|
||||
valueObject = list;
|
||||
}
|
||||
// String
|
||||
else {
|
||||
valueObject = value;
|
||||
}
|
||||
return valueObject;
|
||||
}
|
||||
|
||||
public static Map<String, Object> parseDouyuSttStringToMap(String string) {
|
||||
Map<String, Object> stringObjectMap = new HashMap<>();
|
||||
for (String s : string.split(END)) {
|
||||
String[] entry = s.split(SPLITTER);
|
||||
String key = unescape(entry[0]);
|
||||
String value = unescape(ArrayUtil.get(entry, 1));
|
||||
Object valueObject = parseDouyuSttStringToObject(value);
|
||||
stringObjectMap.put(key, valueObject);
|
||||
}
|
||||
return stringObjectMap;
|
||||
}
|
||||
|
||||
public static <T extends IDouyuMsg> Class<T> getDouyuMsgClassByType(DouyuCmdEnum douyuCmdEnum, short msgType) {
|
||||
if (douyuCmdEnum == null) {
|
||||
return (Class<T>) DouyuCmdMsg.class;
|
||||
}
|
||||
|
||||
Class<?> msgClass;
|
||||
Class<?> tClass = douyuCmdEnum.getTClass();
|
||||
if (tClass == null) {
|
||||
if (douyuCmdEnum == DouyuCmdEnum.mrkl) {
|
||||
if (msgType == MSG_TYPE_RECEIVE) {
|
||||
msgClass = HeartbeatReplyMsg.class;
|
||||
} else if (msgType == MSG_TYPE_SEND) {
|
||||
msgClass = HeartbeatMsg.class;
|
||||
} else {
|
||||
msgClass = null;
|
||||
}
|
||||
} else {
|
||||
msgClass = DouyuCmdMsg.class;
|
||||
}
|
||||
} else {
|
||||
msgClass = tClass;
|
||||
}
|
||||
return (Class<T>) msgClass;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package tech.ordinaryroad.live.chat.client.douyu.api;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.dto.GiftPropSingle;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/30
|
||||
*/
|
||||
class DouyuApisTest {
|
||||
|
||||
@Test
|
||||
void getRealRoomId() {
|
||||
assertEquals(2947432, DouyuApis.getRealRoomId(92000));
|
||||
assertEquals(3168536, DouyuApis.getRealRoomId(3168536));
|
||||
assertEquals(290935, DouyuApis.getRealRoomId(22222));
|
||||
assertEquals(290935, DouyuApis.getRealRoomId(290935));
|
||||
assertEquals(520, DouyuApis.getRealRoomId(520));
|
||||
assertThrows(RuntimeException.class, () -> DouyuApis.getRealRoomId(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getGiftInfo() {
|
||||
GiftPropSingle giftByPid = DouyuApis.getGiftPropSingleByPid("4");
|
||||
assertEquals("赞", giftByPid.getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ChatChoice implements Serializable {
|
||||
private long index;
|
||||
/**
|
||||
* 请求参数stream为true返回是delta
|
||||
*/
|
||||
@JsonProperty("delta")
|
||||
private Message delta;
|
||||
/**
|
||||
* 请求参数stream为false返回是message
|
||||
*/
|
||||
@JsonProperty("message")
|
||||
private Message message;
|
||||
@JsonProperty("finish_reason")
|
||||
private String finishReason;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 描述: chat答案类
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ChatCompletionResponse implements Serializable {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String model;
|
||||
private List<ChatChoice> choices;
|
||||
private Usage usage;
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 OrdinaryRoad
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.BaseMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.config.DouyuLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.constant.DouyuCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.listener.IDouyuMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.ChatmsgMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.DgbMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.UenterMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.netty.handler.DouyuConnectionHandler;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@Slf4j
|
||||
class DouyuLiveChatClientTest implements IDouyuConnectionListener, IDouyuMsgListener {
|
||||
|
||||
static Object lock = new Object();
|
||||
DouyuLiveChatClient client;
|
||||
|
||||
private final OkHttpClient okClient = new OkHttpClient();
|
||||
private static final String API_KEY = "sk-xxxxxx";
|
||||
private static final String URL = "https://api.pandarobot.chat/v1/chat/completions";
|
||||
|
||||
private final Lock reentrantLock = new ReentrantLock();
|
||||
private boolean isProcessing = false;
|
||||
|
||||
|
||||
public String getChatGptResponse(String prompt){
|
||||
if (!reentrantLock.tryLock()) {
|
||||
// 如果无法立即获得锁,直接返回空字符串
|
||||
log.info("自动回复:我还没准备好");
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
if (isProcessing) {
|
||||
log.info("自动回复:我还没准备好");
|
||||
// 如果已经在处理中,直接返回
|
||||
return "";
|
||||
}
|
||||
isProcessing = true;
|
||||
// 你的原始代码逻辑
|
||||
RequestBody body = RequestBody.create(MediaType.get("application/json; charset=utf-8"),
|
||||
"{\"model\": \"gpt-4-0125-preview\", \"messages\": [{\"role\": \"system\", \"content\": \"扮演一个充满机智和幽默感的斗鱼直播弹幕助手,你的任务是用不超过30字的诙谐小段子来回复直播间用户的评论。你的回复应该机智幽默,不夸张能引发笑声,同时也要和谐适应直播间的气氛。当你收到用户的评论时,迅速给出一个既幽默又贴切的回复。例如:评论: 今天的直播怎么样?回复: 好看得让人忘记摸鱼,专心变成鱼粉!\"}, {\"role\": \"user\", \"content\": \"" + prompt + "\"}]}");
|
||||
Request request = new Request.Builder()
|
||||
.url(URL)
|
||||
.post(body)
|
||||
.addHeader("Authorization", "Bearer " + API_KEY)
|
||||
.build();
|
||||
|
||||
long startTime = System.currentTimeMillis(); // 获取开始时间的毫秒数
|
||||
System.out.println("执行前.......");
|
||||
Thread.sleep(3000);
|
||||
System.out.println("执行后.......");
|
||||
long endTime = System.currentTimeMillis(); // 获取结束时间的毫秒数
|
||||
long timeDiff = endTime - startTime; // 计算时间差
|
||||
System.out.println("执行时间 " + timeDiff / 1000 + " 秒。");
|
||||
|
||||
try (Response response = okClient.newCall(request).execute()) {
|
||||
if (response.body() != null) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
ChatCompletionResponse completionResponse = mapper.readValue(response.body().string(), ChatCompletionResponse.class);
|
||||
return completionResponse.getChoices().get(0).getMessage().getContent();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("调用出错了{}",e.getMessage());
|
||||
}
|
||||
return "";
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
isProcessing = false;
|
||||
reentrantLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void example() throws InterruptedException {
|
||||
String cookie = "dy_did=621fbe7a636002f6e6cc42eb00091701; acf_did=621fbe7a636002f6e6cc42eb00091701; dy_teen_mode=%7B%22uid%22%3A%22145703733%22%2C%22status%22%3A0%2C%22birthday%22%3A%22%22%2C%22password%22%3A%22%22%7D; dy_did=621fbe7a636002f6e6cc42eb00091701; Hm_lvt_e99aee90ec1b2106afe7ec3b199020a7=1706978160,1707033428,1707109487; PHPSESSID=1orrfq0m0gfrbd58slgh6shqc7; acf_auth=c22dT%2BYJG1xQ3ZuNrfxYNS06lnIjzNl%2F58xziUwyAsNedpJWvbEtIBh%2Bq%2F%2FYxo%2FFYAp9aQr4i4iYqTp2kYdb7n2JNUFBwGEBgZ8GiGS6O%2FR0CNLy8kQ2iVw; dy_auth=d0d0Ps%2FEOPWjXoPGMenITKuiBIC7wTua3heP19LVKzOZ8qibQpmTA9Hpyx%2FdxtDei1Db6KUWkzq1fEC0BLSZVSUbDkuv%2FX%2F%2B0pMu1kgXnk%2FUzQ%2BhV3EiRf8; wan_auth37wan=f0a9656c2e00K9uFDlpgnTfrv3m8aZoYB0WQTWxGSrSccCMd9LUiEUD2oYpJ%2F5Oe5uD2tVpaUA69sGzlTAtl9p3uLSSqgrvH%2F8sy1gWyyrS4fxotQSU; acf_uid=145703733; acf_username=145703733; acf_nickname=%E5%9B%BE%E5%85%94%E5%85%94%E7%9A%84%E5%85%94%E5%85%94%E5%9B%BE; acf_own_room=0; acf_groupid=1; acf_phonestatus=1; acf_avatar=https%3A%2F%2Fapic.douyucdn.cn%2Fupload%2Favanew%2Fface%2F201706%2F25%2F21%2F82973545fd6b770fe03175783ffbc3d5_; acf_ct=0; acf_ltkid=28814433; acf_biz=1; acf_stk=1213d18dc8e6b5b1; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=1707141953";
|
||||
DouyuLiveChatClientConfig config = DouyuLiveChatClientConfig.builder()
|
||||
// TODO 修改房间id(支持短id)
|
||||
.roomId(7828414)
|
||||
.cookie(cookie)
|
||||
.build();
|
||||
|
||||
client = new DouyuLiveChatClient(config, new IDouyuMsgListener() {
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
IDouyuMsgListener.super.onMsg(binaryFrameHandler, msg);
|
||||
// log.debug("{} 收到{}消息 {}", binaryFrameHandler.getRoomId(), msg.getClass(), msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDanmuMsg(DouyuBinaryFrameHandler binaryFrameHandler, ChatmsgMsg msg) {
|
||||
if(Integer.parseInt(msg.getLevel())>5){
|
||||
String chatGptResponse = getChatGptResponse(msg.getContent());
|
||||
log.info("自动回复:"+ "@"+msg.getUsername()+": "+chatGptResponse);
|
||||
if(!Objects.equals(chatGptResponse, "")){
|
||||
client.sendDanmu("@"+msg.getUsername()+": "+chatGptResponse);
|
||||
}
|
||||
}
|
||||
log.info("{} 收到弹幕 {} {}({}):{}", binaryFrameHandler.getRoomId(), msg.getBadgeLevel() != 0 ? msg.getBadgeLevel() + msg.getBadgeName() : "", msg.getUsername(), msg.getUid(), msg.getContent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGiftMsg(DouyuBinaryFrameHandler binaryFrameHandler, DgbMsg msg) {
|
||||
IDouyuMsgListener.super.onGiftMsg(binaryFrameHandler, msg);
|
||||
// log.info("{} 收到礼物 {} {}({}) {} {}({})x{}({})", binaryFrameHandler.getRoomId(), msg.getBadgeLevel() != 0 ? msg.getBadgeLevel() + msg.getBadgeName() : "", msg.getUsername(), msg.getUid(), "赠送", msg.getGiftName(), msg.getGiftId(), msg.getGiftCount(), msg.getGiftPrice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterRoomMsg(UenterMsg msg) {
|
||||
// if(msg.getLevel()>20){
|
||||
// String chatGptResponse = getChatGptResponse(msg.getUsername()+"加入了直播间,请你帮忙编写简短有创意的欢迎语");
|
||||
// if(!Objects.equals(chatGptResponse, "")){
|
||||
// client.sendDanmu(chatGptResponse);
|
||||
// }
|
||||
// }
|
||||
log.info("{} {}({}) 进入直播间", msg.getBadgeLevel() != 0 ? msg.getBadgeLevel() + msg.getBadgeName() : "", msg.getUsername(), msg.getUid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCmdMsg(DouyuBinaryFrameHandler binaryFrameHandler, DouyuCmdEnum cmd, BaseCmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
IDouyuMsgListener.super.onCmdMsg(binaryFrameHandler, cmd, cmdMsg);
|
||||
//log.info("{} 收到CMD消息{} {}", binaryFrameHandler.getRoomId(), cmd, cmdMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOtherCmdMsg(DouyuBinaryFrameHandler binaryFrameHandler, DouyuCmdEnum cmd, BaseCmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
IDouyuMsgListener.super.onOtherCmdMsg(binaryFrameHandler, cmd, cmdMsg);
|
||||
|
||||
// log.debug("{} 收到其他CMD消息 {}", binaryFrameHandler.getRoomId(), cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnknownCmd(DouyuBinaryFrameHandler binaryFrameHandler, String cmdString, BaseMsg msg) {
|
||||
IDouyuMsgListener.super.onUnknownCmd(binaryFrameHandler, cmdString, msg);
|
||||
|
||||
// log.debug("{} 收到未知CMD消息 {}", binaryFrameHandler.getRoomId(), cmdString);
|
||||
}
|
||||
}, new IDouyuConnectionListener() {
|
||||
@Override
|
||||
public void onConnected(DouyuConnectionHandler connectionHandler) {
|
||||
log.info("{} onConnected", connectionHandler.getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailed(DouyuConnectionHandler connectionHandler) {
|
||||
log.info("{} onConnectFailed", connectionHandler.getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(DouyuConnectionHandler connectionHandler) {
|
||||
log.info("{} onDisconnected", connectionHandler.getRoomId());
|
||||
}
|
||||
});
|
||||
client.connect();
|
||||
|
||||
// 防止测试时直接退出
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipyListeners() throws InterruptedException {
|
||||
DouyuLiveChatClientConfig config = DouyuLiveChatClientConfig.builder()
|
||||
// TODO 修改房间id(支持短id)
|
||||
.roomId(74751)
|
||||
.build();
|
||||
|
||||
client = new DouyuLiveChatClient(config, null, this);
|
||||
client.addMsgListener(new IDouyuMsgListener() {
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
log.info("listener 1 onMsg {}", msg);
|
||||
}
|
||||
});
|
||||
IDouyuMsgListener msgListener2 = new IDouyuMsgListener() {
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
log.info("listener 2 onMsg {}", msg);
|
||||
}
|
||||
};
|
||||
client.addMsgListener(msgListener2);
|
||||
AtomicBoolean removed = new AtomicBoolean(false);
|
||||
client.addMsgListener(new IDouyuMsgListener() {
|
||||
@Override
|
||||
public void onMsg(DouyuBinaryFrameHandler binaryFrameHandler, IMsg msg) {
|
||||
log.info("listener 3 onMsg {}", msg);
|
||||
if (!removed.get()) {
|
||||
log.warn("remove listener 2 by listener 3");
|
||||
removed.set(client.removeMsgListener(msgListener2));
|
||||
}
|
||||
}
|
||||
});
|
||||
client.connect();
|
||||
|
||||
// 防止测试时直接退出
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiplyClient() throws InterruptedException {
|
||||
DouyuLiveChatClientConfig config1 = DouyuLiveChatClientConfig.builder().roomId(890074).build();
|
||||
DouyuLiveChatClient client1 = new DouyuLiveChatClient(config1, DouyuLiveChatClientTest.this, DouyuLiveChatClientTest.this);
|
||||
|
||||
DouyuLiveChatClientConfig config2 = DouyuLiveChatClientConfig.builder().roomId(718133).build();
|
||||
DouyuLiveChatClient client2 = new DouyuLiveChatClient(config2, DouyuLiveChatClientTest.this, DouyuLiveChatClientTest.this);
|
||||
|
||||
client1.connect(() -> {
|
||||
log.warn("client1 connect successfully, start connecting client2");
|
||||
client2.connect(() -> {
|
||||
log.warn("client2 connect successfully");
|
||||
});
|
||||
});
|
||||
|
||||
// 防止测试时直接退出
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendDanmu() throws InterruptedException {
|
||||
String cookie = "dy_did=621fbe7a636002f6e6cc42eb00091701; acf_did=621fbe7a636002f6e6cc42eb00091701; Hm_lvt_e99aee90ec1b2106afe7ec3b199020a7=1706978160; PHPSESSID=5mg98bkoens5bsg7da6ooj74b7; acf_auth=2a246MCoU1hPn940VxZrs0wQVc8tY96s6rHocobTmUJF8XKjoxWmv51PLf1V4T5g8QiEAyy6u%2BHQfC%2FTNkJudUVdEowNqAF81eaUzHvo5i1MIXBRbDXYXwY; dy_auth=d066mz7%2BE83QjmEJfujfi%2FyOuib9Y2qfBcK7pINX6Gde4HGRaiWZxhNXkqdbLU1aV%2FXaQ0wbkyxV0DddiF9jBc4tMpCMjvi4a1C6EJTfpLHvMmaGBKlI%2FlQ; wan_auth37wan=b747c445309bcOqiaMF72xt346irN4v%2Fhi%2BgabHCNxe812jm9rR8kGws8cdJlsn0C6jxsVKY6We5xWlrjHKesoD2%2B0Av52%2FWzIxaZKT0f30GASOJz58; acf_uid=145703733; acf_username=145703733; acf_nickname=%E5%9B%BE%E5%85%94%E5%85%94%E7%9A%84%E5%85%94%E5%85%94%E5%9B%BE; acf_own_room=0; acf_groupid=1; acf_phonestatus=1; acf_avatar=https%3A%2F%2Fapic.douyucdn.cn%2Fupload%2Favanew%2Fface%2F201706%2F25%2F21%2F82973545fd6b770fe03175783ffbc3d5_; acf_ct=0; acf_ltkid=28814429; acf_biz=1; acf_stk=0fad5f2454193f86; dy_teen_mode=%7B%22uid%22%3A%22145703733%22%2C%22status%22%3A0%2C%22birthday%22%3A%22%22%2C%22password%22%3A%22%22%7D; dy_did=621fbe7a636002f6e6cc42eb00091701; acf_ccn=5ba506efe2d8a939cf09f8597c7d8030; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=1706978671";
|
||||
// log.error("cookie: {}", cookie);
|
||||
DouyuLiveChatClientConfig config = DouyuLiveChatClientConfig.builder()
|
||||
.cookie(cookie)
|
||||
// TODO 修改弹幕发送最短时间间隔,默认3s
|
||||
.minSendDanmuPeriod(10 * 1000)
|
||||
// TODO 修改房间id(支持短id)
|
||||
.roomId(4624967)
|
||||
.build();
|
||||
DouyuWsLiveChatClient client = new DouyuWsLiveChatClient(config, new IDouyuMsgListener() {
|
||||
@Override
|
||||
public void onMsg(IMsg msg) {
|
||||
IDouyuMsgListener.super.onMsg(msg);
|
||||
|
||||
// log.debug("收到消息 {}", msg.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCmdMsg(DouyuCmdEnum cmd, BaseCmdMsg<DouyuCmdEnum> cmdMsg) {
|
||||
log.debug("收到CMD消息 {} {}", cmd, cmdMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterRoomMsg(UenterMsg msg) {
|
||||
log.info("{} {}({}) 进入直播间", msg.getBadgeLevel() != 0 ? msg.getBadgeLevel() + msg.getBadgeName() : "", msg.getUsername(), msg.getUid());
|
||||
}
|
||||
@Override
|
||||
public void onUnknownCmd(String cmdString, BaseMsg msg) {
|
||||
IDouyuMsgListener.super.onUnknownCmd(cmdString, msg);
|
||||
|
||||
log.debug("收到未知CMD消息 {} {}", cmdString, msg);
|
||||
}
|
||||
}, new IDouyuConnectionListener() {
|
||||
@Override
|
||||
public void onConnected(DouyuConnectionHandler connectionHandler) {
|
||||
log.error("{} onConnected", connectionHandler.getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailed(DouyuConnectionHandler connectionHandler) {
|
||||
log.error("{} onConnectFailed", connectionHandler.getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(DouyuConnectionHandler connectionHandler) {
|
||||
log.error("{} onDisconnected", connectionHandler.getRoomId());
|
||||
}
|
||||
}, new NioEventLoopGroup());
|
||||
client.connect(() -> {
|
||||
client.sendDanmu("主播真好看");
|
||||
});
|
||||
|
||||
// 防止测试时直接退出
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void createAuthFrameFailedAndDisconnect() throws InterruptedException {
|
||||
DouyuLiveChatClientConfig config = DouyuLiveChatClientConfig.builder()
|
||||
// TODO 修改房间id(支持短id)
|
||||
.autoReconnect(false)
|
||||
.cookie("12323232'123'213'2'13'2")
|
||||
.roomId(22222)
|
||||
.build();
|
||||
|
||||
client = new DouyuLiveChatClient(config, this, this);
|
||||
client.connect();
|
||||
|
||||
// 防止测试时直接退出
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void autoReconnect() throws InterruptedException {
|
||||
DouyuLiveChatClientConfig config = DouyuLiveChatClientConfig.builder()
|
||||
// TODO 修改房间id(支持短id)
|
||||
.autoReconnect(true)
|
||||
.cookie("12323232'123'213'2'13'2")
|
||||
// .websocketUri("wss://sa.asd.asd:12")
|
||||
.roomId(22222)
|
||||
.build();
|
||||
|
||||
client = new DouyuLiveChatClient(config, this, this);
|
||||
client.addStatusChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
Object oldStatus = evt.getOldValue();
|
||||
Object newStatus = evt.getNewValue();
|
||||
log.error("{} => {}", oldStatus, newStatus);
|
||||
}
|
||||
});
|
||||
client.connect();
|
||||
|
||||
// 防止测试时直接退出
|
||||
while (true) {
|
||||
synchronized (lock) {
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(DouyuConnectionHandler connectionHandler) {
|
||||
log.info("{} onConnected", connectionHandler.getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailed(DouyuConnectionHandler connectionHandler) {
|
||||
log.info("{} onConnectFailed", connectionHandler.getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(DouyuConnectionHandler connectionHandler) {
|
||||
log.info("{} onDisconnected", connectionHandler.getRoomId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDanmuMsg(DouyuBinaryFrameHandler binaryFrameHandler, ChatmsgMsg msg) {
|
||||
IDouyuMsgListener.super.onDanmuMsg(binaryFrameHandler, msg);
|
||||
|
||||
log.info("{} 收到弹幕 {}({}):{}", binaryFrameHandler.getRoomId(), msg.getNn(), msg.getUid(), msg.getTxt());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* @since 2023-03-02
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Message implements Serializable {
|
||||
|
||||
/**
|
||||
* 目前支持四个中角色参考官网,进行情景输入:
|
||||
* https://platform.openai.com/docs/guides/chat/introduction
|
||||
*/
|
||||
private String role;
|
||||
|
||||
private String content;
|
||||
|
||||
private String name;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param role 角色
|
||||
* @param content 描述主题信息
|
||||
* @param name name
|
||||
*/
|
||||
public Message(String role, String content, String name) {
|
||||
this.role = role;
|
||||
this.content = content;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Message() {
|
||||
}
|
||||
|
||||
private Message(Builder builder) {
|
||||
setRole(builder.role);
|
||||
setContent(builder.content);
|
||||
setName(builder.name);
|
||||
}
|
||||
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Role {
|
||||
|
||||
SYSTEM("system"),
|
||||
USER("user"),
|
||||
ASSISTANT("assistant"),
|
||||
FUNCTION("function"),
|
||||
;
|
||||
private String name;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String role;
|
||||
private String content;
|
||||
private String name;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder role(Role role) {
|
||||
this.role = role.getName();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder role(String role) {
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Message build() {
|
||||
return new Message(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package tech.ordinaryroad.live.chat.client.douyu.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
* @author https:www.unfbx.com
|
||||
* 2023-02-15
|
||||
*/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Usage implements Serializable {
|
||||
@JsonProperty("prompt_tokens")
|
||||
private long promptTokens;
|
||||
@JsonProperty("completion_tokens")
|
||||
private long completionTokens;
|
||||
@JsonProperty("total_tokens")
|
||||
private long totalTokens;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package tech.ordinaryroad.live.chat.client.douyu.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.BaseDouyuCmdMsg;
|
||||
import tech.ordinaryroad.live.chat.client.douyu.msg.base.IDouyuMsg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
class DouyuCodecUtilTest {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
String loginres = "type@=loginres/userid@=1235403446/roomgroup@=0/pg@=0/sessionid@=0/username@=/nickname@=/live_stat@=0/is_illegal@=0/ill_ct@=/ill_ts@=0/now@=0/ps@=0/es@=0/it@=0/its@=0/npv@=0/best_dlev@=0/cur_lev@=0/nrc@=2785047409/ih@=0/sid@=72256/sahf@=0/sceneid@=0/newrg@=0/regts@=0/ip@=112.43.93.229/rn@=0/rct@=0/";
|
||||
String pingreq = "type@=pingreq/tick@=1693128084471/";
|
||||
String mrkl = "type@=mrkl/";
|
||||
String subres = "type@=subres/res@=0/";
|
||||
String mapkb = "type@=mapkb/cmd@=3/rid@=5515841/pk_time@=600/lt@=156/teams@=team@AA=5@ASres@AA=1@ASsc@AA=660000@ASbf@AA=0@AS@Steam@AA=6@ASres@AA=2@ASsc@AA=600000@ASbf@AA=0@AS@Steam@AA=4@ASres@AA=3@ASsc@AA=456000@ASbf@AA=0@AS@Steam@AA=2@ASres@AA=4@ASsc@AA=302000@ASbf@AA=0@AS@Steam@AA=3@ASres@AA=5@ASsc@AA=100000@ASbf@AA=0@AS@Steam@AA=1@ASres@AA=6@ASsc@AA=200@ASbf@AA=0@AS@S/members@=rid@AA=5515841@ASuid@AA=219585944@ASnick@AA=喵小莎@ASicon@AA=avatar_v3@AAS202303@AAS4cab38d935004acfab53f77a730c9d42@ASstatus@AA=0@ASsc@AA=100000@AStime@AA=1693127363@ASteam@AA=3@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=8733064@ASuid@AA=364378905@ASnick@AA=阿允唱情歌@ASicon@AA=avatar_v3@AAS202008@AAS31b239d8af174462b5e0a2990c70b818@ASstatus@AA=0@ASsc@AA=600000@AStime@AA=1693127527@ASteam@AA=6@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=10673032@ASuid@AA=442218984@ASnick@AA=果酱Broly@ASicon@AA=avatar_v3@AAS202306@AASf7d61a0ea3bb4c179af7b5e24f94953e@ASstatus@AA=0@ASsc@AA=200@AStime@AA=1693127347@ASteam@AA=1@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=533813@ASuid@AA=36922190@ASnick@AA=正直博@ASicon@AA=avatar_v3@AAS202212@AAS4e340983996f43b991ffa50af7b956f6@ASstatus@AA=0@ASsc@AA=302000@AStime@AA=1693127348@ASteam@AA=2@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=8031896@ASuid@AA=243111494@ASnick@AA=青榎@ASicon@AA=avatar_v3@AAS202305@AAS8bd800d3bb8d4e16884dcb3e3f77b038@ASstatus@AA=0@ASsc@AA=456000@AStime@AA=1693127393@ASteam@AA=4@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=7009686@ASuid@AA=299482114@ASnick@AA=紫薇同学@ASicon@AA=avatar_v3@AAS202302@AASb67044b78b494b0896fd6738bc2d5b7b@ASstatus@AA=0@ASsc@AA=660000@AStime@AA=1693127424@ASteam@AA=5@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@S/subcmd@=0/pkm@=0/rlt@=0/";
|
||||
String pdrinfo = "giftId@=23518/total@=total@A=3@Snum@A=0@Sfin@A=0@S/actStatus@=1/time@=1693158017596/type@=pdrinfo/dayFin@=0/list@=1@A=total@AAA=6@AASnum@AAA=6@AASpid@AAA=2682@AASfin@AAA=1@AAS@AStotal@AAA=600@AASnum@AAA=336@AASpid@AAA=2680@AASfin@AAA=0@AAS@AS@S100@A=total@AAA=2@AASnum@AAA=0@AASpid@AAA=2685@AASfin@AAA=0@AAS@AStotal@AAA=100@AASnum@AAA=5@AASpid@AAA=2682@AASfin@AAA=0@AAS@AS@S10@A=total@AAA=2@AASnum@AAA=0@AASpid@AAA=2683@AASfin@AAA=0@AAS@AStotal@AAA=80@AASnum@AAA=35@AASpid@AAA=2681@AASfin@AAA=0@AAS@AS@S/";
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("loginres", loginres);
|
||||
map.put("pingreq", pingreq);
|
||||
map.put("mrkl", mrkl);
|
||||
map.put("subres", subres);
|
||||
map.put("mapkb", mapkb);
|
||||
map.put("pdrinfo", pdrinfo);
|
||||
|
||||
map.forEach((string, string2) -> {
|
||||
BaseDouyuCmdMsg baseDouyuCmdMsg = (BaseDouyuCmdMsg) DouyuCodecUtil.parseDouyuSttString(string2, DouyuCodecUtil.MSG_TYPE_RECEIVE);
|
||||
assertNotNull(baseDouyuCmdMsg);
|
||||
String cmd = baseDouyuCmdMsg.getCmd();
|
||||
assertEquals(string, cmd);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeTest() {
|
||||
String mapkb = "type@=mapkb/cmd@=3/rid@=5515841/pk_time@=600/lt@=156/teams@=team@AA=5@ASres@AA=1@ASsc@AA=660000@ASbf@AA=0@AS@Steam@AA=6@ASres@AA=2@ASsc@AA=600000@ASbf@AA=0@AS@Steam@AA=4@ASres@AA=3@ASsc@AA=456000@ASbf@AA=0@AS@Steam@AA=2@ASres@AA=4@ASsc@AA=302000@ASbf@AA=0@AS@Steam@AA=3@ASres@AA=5@ASsc@AA=100000@ASbf@AA=0@AS@Steam@AA=1@ASres@AA=6@ASsc@AA=200@ASbf@AA=0@AS@S/members@=rid@AA=5515841@ASuid@AA=219585944@ASnick@AA=喵小莎@ASicon@AA=avatar_v3@AAS202303@AAS4cab38d935004acfab53f77a730c9d42@ASstatus@AA=0@ASsc@AA=100000@AStime@AA=1693127363@ASteam@AA=3@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=8733064@ASuid@AA=364378905@ASnick@AA=阿允唱情歌@ASicon@AA=avatar_v3@AAS202008@AAS31b239d8af174462b5e0a2990c70b818@ASstatus@AA=0@ASsc@AA=600000@AStime@AA=1693127527@ASteam@AA=6@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=10673032@ASuid@AA=442218984@ASnick@AA=果酱Broly@ASicon@AA=avatar_v3@AAS202306@AASf7d61a0ea3bb4c179af7b5e24f94953e@ASstatus@AA=0@ASsc@AA=200@AStime@AA=1693127347@ASteam@AA=1@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=533813@ASuid@AA=36922190@ASnick@AA=正直博@ASicon@AA=avatar_v3@AAS202212@AAS4e340983996f43b991ffa50af7b956f6@ASstatus@AA=0@ASsc@AA=302000@AStime@AA=1693127348@ASteam@AA=2@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=8031896@ASuid@AA=243111494@ASnick@AA=青榎@ASicon@AA=avatar_v3@AAS202305@AAS8bd800d3bb8d4e16884dcb3e3f77b038@ASstatus@AA=0@ASsc@AA=456000@AStime@AA=1693127393@ASteam@AA=4@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@Srid@AA=7009686@ASuid@AA=299482114@ASnick@AA=紫薇同学@ASicon@AA=avatar_v3@AAS202302@AASb67044b78b494b0896fd6738bc2d5b7b@ASstatus@AA=0@ASsc@AA=660000@AStime@AA=1693127424@ASteam@AA=5@ASgroup_no@AA=0@ASmd@AA=0@AShvsc@AA=0@ASct@AA=0@AS@S/subcmd@=0/pkm@=0/rlt@=0/";
|
||||
Map<String, Object> stringObjectMap = DouyuCodecUtil.parseDouyuSttStringToMap(mapkb);
|
||||
assertNotNull(stringObjectMap);
|
||||
stringObjectMap.forEach((string, o) -> {
|
||||
System.out.println(string);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeTest2() {
|
||||
String pdrinfo = "giftId@=23518/total@=total@A=3@Snum@A=0@Sfin@A=0@S/actStatus@=1/time@=1693158017596/type@=pdrinfo/dayFin@=0/list@=1@A=total@AAA=6@AASnum@AAA=6@AASpid@AAA=2682@AASfin@AAA=1@AAS@AStotal@AAA=600@AASnum@AAA=336@AASpid@AAA=2680@AASfin@AAA=0@AAS@AS@S100@A=total@AAA=2@AASnum@AAA=0@AASpid@AAA=2685@AASfin@AAA=0@AAS@AStotal@AAA=100@AASnum@AAA=5@AASpid@AAA=2682@AASfin@AAA=0@AAS@AS@S10@A=total@AAA=2@AASnum@AAA=0@AASpid@AAA=2683@AASfin@AAA=0@AAS@AStotal@AAA=80@AASnum@AAA=35@AASpid@AAA=2681@AASfin@AAA=0@AAS@AS@S/";
|
||||
Map<String, Object> stringObjectMap = DouyuCodecUtil.parseDouyuSttStringToMap(pdrinfo);
|
||||
assertNotNull(stringObjectMap);
|
||||
stringObjectMap.forEach((string, o) -> {
|
||||
System.out.println(string);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void toDouyuSttStringTest() {
|
||||
String douyuSttString = DouyuCodecUtil.toDouyuSttString(new HashMap<String, Object>() {{
|
||||
put("key1", "value1");
|
||||
put("key2", 2);
|
||||
put("key3", new ArrayList<Map<String, Object>>() {{
|
||||
add(new HashMap<String, Object>() {{
|
||||
put("11", 11);
|
||||
put("12", 12);
|
||||
}});
|
||||
add(new HashMap<String, Object>() {{
|
||||
put("21", 21);
|
||||
put("22", 22);
|
||||
}});
|
||||
}});
|
||||
}});
|
||||
System.out.println(douyuSttString);
|
||||
assertEquals("key1@=value1/key2@=2/key3@=11@AA=11@AS12@AA=12@AS@S22@AA=22@AS21@AA=21@AS@S/".length(), douyuSttString.length());
|
||||
}
|
||||
|
||||
@Test
|
||||
void codecTest() {
|
||||
String mapkb = "type@=mapkb/pk_time@=600/teams@=team@AA=5@ASres@AA=1@ASsc@AA=660000@ASbf@AA=0@AS@Steam@AA=6@ASres@AA=2@ASsc@AA=600000@ASbf@AA=0@AS@Steam@AA=4@ASres@AA=3@ASsc@AA=456000@ASbf@AA=0@AS@Steam@AA=2@ASres@AA=4@ASsc@AA=302000@ASbf@AA=0@AS@Steam@AA=3@ASres@AA=5@ASsc@AA=100000@ASbf@AA=0@AS@Steam@AA=1@ASres@AA=6@ASsc@AA=200@ASbf@AA=0@AS@S/";
|
||||
IDouyuMsg iDouyuMsg = DouyuCodecUtil.parseDouyuSttString(mapkb, DouyuCodecUtil.MSG_TYPE_RECEIVE);
|
||||
String douyuSttString = DouyuCodecUtil.toDouyuSttString(iDouyuMsg);
|
||||
System.out.println(mapkb);
|
||||
System.out.println(douyuSttString);
|
||||
assertEquals(mapkb.length(), douyuSttString.length());
|
||||
IDouyuMsg douyuSttStringMsg = DouyuCodecUtil.parseDouyuSttString(douyuSttString, DouyuCodecUtil.MSG_TYPE_RECEIVE);
|
||||
assertNotNull(douyuSttStringMsg);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unescape() {
|
||||
String unescape = DouyuCodecUtil.unescape("team@AA=5@ASres@AA=1@ASsc@AA=660000@ASbf@AA=0@AS@Steam@AA=6@ASres@AA=2@ASsc@AA=600000@ASbf@AA=0@AS@Steam@AA=4@ASres@AA=3@ASsc@AA=456000@ASbf@AA=0@AS@Steam@AA=2@ASres@AA=4@ASsc@AA=302000@ASbf@AA=0@AS@Steam@AA=3@ASres@AA=5@ASsc@AA=100000@ASbf@AA=0@AS@Steam@AA=1@ASres@AA=6@ASsc@AA=200@ASbf@AA=0@AS@S");
|
||||
System.out.println(unescape);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user