mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-03-13 20:53:42 +08:00
v1.0.3
This commit is contained in:
16
README.md
16
README.md
@@ -63,7 +63,11 @@
|
||||
</div>
|
||||
|
||||
## 语音克隆
|
||||
https://github.com/ageerle/ruoyi-ai/assets/32251822/62c60f2a-add0-421b-8e32-16ed6a3e598b
|
||||
|
||||
|
||||
https://github.com/ageerle/ruoyi-ai/assets/32251822/c3dd75eb-c5bd-4ab0-93bf-9221f4888827
|
||||
|
||||
|
||||
|
||||
## 弹幕助手
|
||||
|
||||
@@ -72,10 +76,14 @@ https://github.com/ageerle/ruoyi-ai/assets/32251822/2d809d94-6cfb-41b1-9dc0-a72c
|
||||
|
||||
|
||||
|
||||
## 私有知识库管理(开发中)
|
||||
## 私有知识库管理
|
||||
<div>
|
||||
<img style="margin-top:10px" src="./image/12.png" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px" src="./image/私有知识库业务架构图.drawio.png" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px;width:50%" src="./image/12.png" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px;width:50%" src="./image/私有知识库业务架构图.drawio.png" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px;width:50%" src="https://github.com/ageerle/ruoyi-ai/assets/32251822/6d44ebcc-1ec4-43e0-b164-cac150e8a044" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px;width:50%" src="https://github.com/ageerle/ruoyi-ai/assets/32251822/fbd50daf-19d9-4e0f-8e5e-8603af5fb520" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px;width:50%" src="https://github.com/ageerle/ruoyi-ai/assets/32251822/b14dffe7-2ae1-4fa3-8bb0-bf0b44d7ebd9" alt="drawing" width="550px" height="300px"/>
|
||||
<img style="margin-top:10px;width:50%" src="https://github.com/ageerle/ruoyi-ai/assets/32251822/4ae97a41-f1d2-4bb2-966f-83211193a115" alt="drawing" width="550px" height="300px"/>
|
||||
</div>
|
||||
|
||||
## 进群学习
|
||||
|
||||
BIN
image/02.png
Normal file
BIN
image/02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
2
pom.xml
2
pom.xml
@@ -324,6 +324,8 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-generator</artifactId>
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
#基础镜像
|
||||
FROM findepi/graalvm:java17-native
|
||||
|
||||
MAINTAINER Lion Li
|
||||
MAINTAINER ageerle
|
||||
|
||||
RUN mkdir -p /ruoyi/server/logs \
|
||||
/ruoyi/server/temp \
|
||||
/ruoyi/skywalking/agent
|
||||
|
||||
|
||||
#工作空间
|
||||
WORKDIR /ruoyi/server
|
||||
|
||||
ENV SERVER_PORT=8080
|
||||
ENV SERVER_PORT=6039
|
||||
|
||||
EXPOSE ${SERVER_PORT}
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@
|
||||
<artifactId>ruoyi-midjourney</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 代码生成-->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
|
||||
@@ -45,8 +45,6 @@ public class AuthController {
|
||||
private final SysRegisterService registerService;
|
||||
private final ISysTenantService tenantService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
*
|
||||
|
||||
@@ -85,6 +85,7 @@ public class CaptchaController {
|
||||
*
|
||||
* @param emailRequest 用户邮箱
|
||||
*/
|
||||
//@PostMapping("/resource/email/code")
|
||||
@PostMapping("/resource/email/code")
|
||||
public R<Void> emailCode(@RequestBody @Valid EmailRequest emailRequest) {
|
||||
if (!mailProperties.getEnabled()) {
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.xmzs.controller;
|
||||
|
||||
import com.xmzs.common.chat.domain.request.ChatRequest;
|
||||
import com.xmzs.common.chat.domain.request.Dall3Request;
|
||||
import com.xmzs.common.chat.domain.request.MjTaskRequest;
|
||||
import com.xmzs.common.chat.entity.Tts.TextToSpeech;
|
||||
import com.xmzs.common.chat.entity.files.UploadFileResponse;
|
||||
import com.xmzs.common.chat.entity.images.Item;
|
||||
import com.xmzs.common.chat.entity.whisper.WhisperResponse;
|
||||
import com.xmzs.common.core.domain.R;
|
||||
@@ -21,25 +21,15 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* 描述:
|
||||
*
|
||||
@@ -64,6 +54,16 @@ public class ChatController {
|
||||
return ISseService.sseChat(chatRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
@PostMapping("/v1/upload")
|
||||
@ResponseBody
|
||||
public UploadFileResponse upload(@RequestPart("file") MultipartFile file) {
|
||||
return ISseService.upload(file);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 语音转文本
|
||||
*
|
||||
@@ -94,18 +94,6 @@ public class ChatController {
|
||||
return R.ok(ISseService.dall3(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 扣除mj绘图费用
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/mjTask")
|
||||
@ResponseBody
|
||||
public R<String> mjTask(@RequestBody MjTaskRequest mjTaskRequest) {
|
||||
ISseService.mjTask(mjTaskRequest);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 聊天记录
|
||||
*/
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.xmzs.system.domain.vo.SysUserVo;
|
||||
import com.xmzs.system.service.IPaymentOrdersService;
|
||||
import com.xmzs.system.service.ISysUserService;
|
||||
import com.xmzs.system.util.OrderNumberGenerator;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -43,15 +42,16 @@ public class PayController {
|
||||
|
||||
private final IPaymentOrdersService paymentOrdersService;
|
||||
|
||||
private final PayConfig payConfig;
|
||||
|
||||
/**
|
||||
* 获取支付二维码
|
||||
*
|
||||
* @Date 2023/7/3
|
||||
* @param response
|
||||
* @return void
|
||||
**/
|
||||
@PostMapping("/payUrl")
|
||||
public R<PaymentOrdersVo> payUrl(HttpServletResponse response, @RequestBody OrderRequest orderRequest) {
|
||||
public R<PaymentOrdersVo> payUrl(@RequestBody OrderRequest orderRequest) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
// 创建订单
|
||||
PaymentOrdersBo paymentOrders = new PaymentOrdersBo();
|
||||
@@ -115,9 +115,9 @@ public class PayController {
|
||||
public String returnUrl(PayResponse payResponse) {
|
||||
// 校验签名
|
||||
String mdString = "money=" + payResponse.getMoney() + "&name=" + payResponse.getName() +
|
||||
"&out_trade_no=" + payResponse.getOut_trade_no() + "&pid=" + PayConfig.pid +
|
||||
"&out_trade_no=" + payResponse.getOut_trade_no() + "&pid=" + payConfig.getPid() +
|
||||
"&trade_no=" + payResponse.getTrade_no() + "&trade_status=" + payResponse.getTrade_status() +
|
||||
"&type=" + payResponse.getType() + PayConfig.key;
|
||||
"&type=" + payResponse.getType() + payConfig.getKey();
|
||||
String sign = MD5Util.GetMD5Code(mdString);
|
||||
if(!sign.equals(payResponse.getSign())){
|
||||
throw new BaseException("校验签名失败!");
|
||||
@@ -136,10 +136,8 @@ public class PayController {
|
||||
paymentOrdersVo.setPaymentMethod(payResponse.getType());
|
||||
BeanUtil.copyProperties(paymentOrdersVo,paymentOrdersBo);
|
||||
paymentOrdersService.updateByBo(paymentOrdersBo);
|
||||
|
||||
SysUserVo sysUserVo = userService.selectUserById(paymentOrdersVo.getUserId());
|
||||
if(money>9.9){
|
||||
money = money*2;
|
||||
}
|
||||
sysUserVo.setUserBalance(sysUserVo.getUserBalance()+money);
|
||||
SysUserBo sysUserBo = new SysUserBo();
|
||||
BeanUtil.copyProperties(sysUserVo,sysUserBo);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
enabled: false
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
@@ -51,36 +51,36 @@ spring:
|
||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||
url: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
username: ry-vue
|
||||
password: xxx
|
||||
password: ry-vue
|
||||
|
||||
# 从库数据源
|
||||
# slave:
|
||||
# lazy: true
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
# username:
|
||||
# password:
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||
# username: ROOT
|
||||
# password: root
|
||||
# hikari:
|
||||
# connectionTestQuery: SELECT 1 FROM DUAL
|
||||
# postgres:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||
# username: root
|
||||
# password: root
|
||||
# sqlserver:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
|
||||
# username: SA
|
||||
# password: root
|
||||
# slave:
|
||||
# lazy: true
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||
# username:
|
||||
# password:
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||
# username: ROOT
|
||||
# password: root
|
||||
# hikari:
|
||||
# connectionTestQuery: SELECT 1 FROM DUAL
|
||||
# postgres:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
|
||||
# username: root
|
||||
# password: root
|
||||
# sqlserver:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
|
||||
# username: SA
|
||||
# password: root
|
||||
hikari:
|
||||
# 最大连接池数量
|
||||
maxPoolSize: 20
|
||||
|
||||
@@ -4,7 +4,7 @@ spring.servlet.multipart.location: /ruoyi/server/temp
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
enabled: false
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
|
||||
@@ -212,27 +212,6 @@ mybatis-encryptor:
|
||||
# 公私钥 非对称算法的公私钥 如:SM2,RSA
|
||||
publicKey:
|
||||
privateKey:
|
||||
--- # mail 邮件发送
|
||||
mail:
|
||||
enabled: true
|
||||
host: smtp.163.com
|
||||
port: 465
|
||||
# 是否需要用户名密码验证
|
||||
auth: true
|
||||
# 发送方,遵循RFC-822标准
|
||||
from: ageerle@163.com
|
||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||
user: ageerle@163.com
|
||||
# 密码(填写授权码)
|
||||
pass: xxxx
|
||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||
starttlsEnable: true
|
||||
# 使用SSL安全连接
|
||||
sslEnable: true
|
||||
# SMTP超时时长,单位毫秒,缺省值不超时
|
||||
timeout: 0
|
||||
# Socket连接超时值,单位毫秒,缺省值不超时
|
||||
connectionTimeout: 0
|
||||
|
||||
# Swagger配置
|
||||
swagger:
|
||||
@@ -313,15 +292,12 @@ management:
|
||||
|
||||
--- # websocket
|
||||
websocket:
|
||||
enabled: true
|
||||
enabled: false
|
||||
# 路径
|
||||
path: ''
|
||||
# 设置访问源地址
|
||||
allowedOrigins: '*'
|
||||
# chatgpt配置信息
|
||||
chat:
|
||||
apiKey: 'sk-xxx'
|
||||
apiHost: 'https://api.pandarobot.chat/'
|
||||
|
||||
# 微信小程序配置信息
|
||||
wx:
|
||||
miniapp:
|
||||
@@ -338,6 +314,8 @@ baidu:
|
||||
textReview:
|
||||
apiKey: '' # apiKey
|
||||
secretKey: '' # secretKey
|
||||
appKey: xxxxxxxxxxxxxxxxx
|
||||
secretKey: xxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
wechat:
|
||||
# 是否使用微信 true/false
|
||||
@@ -353,23 +331,62 @@ keyword:
|
||||
image: "ai画图"
|
||||
# ai语音指令(TTS模型 https://platform.openai.com/docs/api-reference/audio)
|
||||
audio: "ai语音"
|
||||
|
||||
mj:
|
||||
api-secret:
|
||||
api-secret: 'sk-xx'
|
||||
task-store:
|
||||
type: in_memory
|
||||
timeout: 30d
|
||||
translate-way: gpt
|
||||
# proxy:
|
||||
# host: 127.0.0.1
|
||||
# port: 10809
|
||||
# proxy:
|
||||
# host: 127.0.0.1
|
||||
# port: 10809
|
||||
ng-discord:
|
||||
server: https://discord.pandarobot.chat/
|
||||
cdn: https://app.pandarobot.chat/
|
||||
wss: https://gateway.pandarobot.chat/
|
||||
server: 'https://xxx.pandarobot.chat/'
|
||||
cdn: 'https://xxx.pandarobot.chat/'
|
||||
wss: 'https://xxx.pandarobot.chat/'
|
||||
openai:
|
||||
gpt-api-url: 'https://api.gptgod.online/'
|
||||
gpt-api-key: 'xxxxxxx'
|
||||
gpt-api-url: 'https://api.pandarobot.chat/'
|
||||
gpt-api-key: 'sk-xx'
|
||||
accounts:
|
||||
- guild-id: 'xxxxxx'
|
||||
channel-id: 'xxxxx'
|
||||
user-token: 'xxxxxxx'
|
||||
- guild-id: 'xx'
|
||||
channel-id: 'xx'
|
||||
user-token: 'xx'
|
||||
|
||||
--- # mail 邮件发送
|
||||
mail:
|
||||
enabled: true
|
||||
host: smtp.163.com
|
||||
port: 465
|
||||
# 是否需要用户名密码验证
|
||||
auth: true
|
||||
# 发送方,遵循RFC-822标准
|
||||
from: ageerle@163.com
|
||||
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
|
||||
user: ageerle@163.com
|
||||
# 密码(填写授权码)
|
||||
pass: TOGXBVPYFVPFRQMQ
|
||||
# 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
|
||||
starttlsEnable: true
|
||||
# 使用SSL安全连接
|
||||
sslEnable: true
|
||||
# SMTP超时时长,单位毫秒,缺省值不超时
|
||||
timeout: 0
|
||||
# Socket连接超时值,单位毫秒,缺省值不超时
|
||||
connectionTimeout: 0
|
||||
|
||||
# chatgpt配置信息
|
||||
chat:
|
||||
apiKey: 'sk-xxx'
|
||||
apiHost: 'https://api.pandarobot.chat/'
|
||||
|
||||
# 支付配置信息
|
||||
pay:
|
||||
pid: 'xxx'
|
||||
key: 'xxx'
|
||||
payUrl: 'https://pay.pandarobot.chat/mapi.php'
|
||||
notify_url: 'https://www.pandarobot.chat/pay/returnUrl'
|
||||
return_url: 'https://www.pandarobot.chat/pay/notifyUrl'
|
||||
type: 'wxpay'
|
||||
device: 'pc'
|
||||
sign_type: 'MD5'
|
||||
|
||||
45
ruoyi-admin/src/test/java/com/xmzs/test/AssertUnitTest.java
Normal file
45
ruoyi-admin/src/test/java/com/xmzs/test/AssertUnitTest.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* 断言单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@DisplayName("断言单元测试案例")
|
||||
public class AssertUnitTest {
|
||||
|
||||
@DisplayName("测试 assertEquals 方法")
|
||||
@Test
|
||||
public void testAssertEquals() {
|
||||
Assertions.assertEquals("666", new String("666"));
|
||||
Assertions.assertNotEquals("666", new String("666"));
|
||||
}
|
||||
|
||||
@DisplayName("测试 assertSame 方法")
|
||||
@Test
|
||||
public void testAssertSame() {
|
||||
Object obj = new Object();
|
||||
Object obj1 = obj;
|
||||
Assertions.assertSame(obj, obj1);
|
||||
Assertions.assertNotSame(obj, obj1);
|
||||
}
|
||||
|
||||
@DisplayName("测试 assertTrue 方法")
|
||||
@Test
|
||||
public void testAssertTrue() {
|
||||
Assertions.assertTrue(true);
|
||||
Assertions.assertFalse(true);
|
||||
}
|
||||
|
||||
@DisplayName("测试 assertNull 方法")
|
||||
@Test
|
||||
public void testAssertNull() {
|
||||
Assertions.assertNull(null);
|
||||
Assertions.assertNotNull(null);
|
||||
}
|
||||
|
||||
}
|
||||
70
ruoyi-admin/src/test/java/com/xmzs/test/DemoUnitTest.java
Normal file
70
ruoyi-admin/src/test/java/com/xmzs/test/DemoUnitTest.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import com.xmzs.common.core.config.RuoYiConfig;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
|
||||
@DisplayName("单元测试案例")
|
||||
public class DemoUnitTest {
|
||||
|
||||
@Autowired
|
||||
private RuoYiConfig ruoYiConfig;
|
||||
|
||||
@DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
|
||||
@Test
|
||||
public void testTest() {
|
||||
System.out.println(ruoYiConfig);
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@DisplayName("测试 @Disabled 注解")
|
||||
@Test
|
||||
public void testDisabled() {
|
||||
System.out.println(ruoYiConfig);
|
||||
}
|
||||
|
||||
@Timeout(value = 2L, unit = TimeUnit.SECONDS)
|
||||
@DisplayName("测试 @Timeout 注解")
|
||||
@Test
|
||||
public void testTimeout() throws InterruptedException {
|
||||
Thread.sleep(3000);
|
||||
System.out.println(ruoYiConfig);
|
||||
}
|
||||
|
||||
|
||||
@DisplayName("测试 @RepeatedTest 注解")
|
||||
@RepeatedTest(3)
|
||||
public void testRepeatedTest() {
|
||||
System.out.println(666);
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void testBeforeAll() {
|
||||
System.out.println("@BeforeAll ==================");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void testBeforeEach() {
|
||||
System.out.println("@BeforeEach ==================");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void testAfterEach() {
|
||||
System.out.println("@AfterEach ==================");
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void testAfterAll() {
|
||||
System.out.println("@AfterAll ==================");
|
||||
}
|
||||
|
||||
}
|
||||
72
ruoyi-admin/src/test/java/com/xmzs/test/ParamUnitTest.java
Normal file
72
ruoyi-admin/src/test/java/com/xmzs/test/ParamUnitTest.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import com.xmzs.common.core.enums.UserType;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.NullSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 带参数单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@DisplayName("带参数单元测试案例")
|
||||
public class ParamUnitTest {
|
||||
|
||||
@DisplayName("测试 @ValueSource 注解")
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"t1", "t2", "t3"})
|
||||
public void testValueSource(String str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
@DisplayName("测试 @NullSource 注解")
|
||||
@ParameterizedTest
|
||||
@NullSource
|
||||
public void testNullSource(String str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
@DisplayName("测试 @EnumSource 注解")
|
||||
@ParameterizedTest
|
||||
@EnumSource(UserType.class)
|
||||
public void testEnumSource(UserType type) {
|
||||
System.out.println(type.getUserType());
|
||||
}
|
||||
|
||||
@DisplayName("测试 @MethodSource 注解")
|
||||
@ParameterizedTest
|
||||
@MethodSource("getParam")
|
||||
public void testMethodSource(String str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
public static Stream<String> getParam() {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("t1");
|
||||
list.add("t2");
|
||||
list.add("t3");
|
||||
return list.stream();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void testBeforeEach() {
|
||||
System.out.println("@BeforeEach ==================");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void testAfterEach() {
|
||||
System.out.println("@AfterEach ==================");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
54
ruoyi-admin/src/test/java/com/xmzs/test/TagUnitTest.java
Normal file
54
ruoyi-admin/src/test/java/com/xmzs/test/TagUnitTest.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.xmzs.test;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* 标签单元测试案例
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@SpringBootTest
|
||||
@DisplayName("标签单元测试案例")
|
||||
public class TagUnitTest {
|
||||
|
||||
@Tag("dev")
|
||||
@DisplayName("测试 @Tag dev")
|
||||
@Test
|
||||
public void testTagDev() {
|
||||
System.out.println("dev");
|
||||
}
|
||||
|
||||
@Tag("prod")
|
||||
@DisplayName("测试 @Tag prod")
|
||||
@Test
|
||||
public void testTagProd() {
|
||||
System.out.println("prod");
|
||||
}
|
||||
|
||||
@Tag("local")
|
||||
@DisplayName("测试 @Tag local")
|
||||
@Test
|
||||
public void testTagLocal() {
|
||||
System.out.println("local");
|
||||
}
|
||||
|
||||
@Tag("exclude")
|
||||
@DisplayName("测试 @Tag exclude")
|
||||
@Test
|
||||
public void testTagExclude() {
|
||||
System.out.println("exclude");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void testBeforeEach() {
|
||||
System.out.println("@BeforeEach ==================");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void testAfterEach() {
|
||||
System.out.println("@AfterEach ==================");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -173,13 +173,15 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 微信模块 -->
|
||||
<!-- AI绘画 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-midjourney</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- 支付模块 -->
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
|
||||
@@ -12,22 +12,27 @@ public class OpenAIConst {
|
||||
|
||||
public final static int SUCCEED_CODE = 200;
|
||||
|
||||
/** GPT3扣除费用 */
|
||||
public final static double GPT3_COST = 0.05;
|
||||
|
||||
public final static double GPT4_COST = 0.3;
|
||||
/** GPT4扣除费用 */
|
||||
public final static double GPT4_COST = 0.2;
|
||||
|
||||
public final static double GPT4_ALL_COST = 0.3;
|
||||
/** DALL普通绘图扣除费用 */
|
||||
public final static double DALL3_COST = 0.3;
|
||||
|
||||
/** 绘图费用 */
|
||||
public final static double DALL3_COST = 0.4;
|
||||
/** DALL高清绘图扣除费用 */
|
||||
public final static double DALL3_HD_COST = 0.5;
|
||||
|
||||
/** 绘图费用-高清 */
|
||||
public final static double DALL3_HD_COST = 0.8;
|
||||
/** MJ操作类型1(变化、变焦、文生图、图生图、局部重绘、混图)扣除费用 */
|
||||
public final static double MJ_COST_TYPE1 = 0.3;
|
||||
|
||||
/** mdjourney绘图费用 */
|
||||
public final static double MJ_COST = 0.3;
|
||||
/** MJ操作类型2(换脸、放大、图生文、prompt分析)扣除费用 */
|
||||
public final static double MJ_COST_TYPE2 = 0.1;
|
||||
|
||||
/** MJ操作类型3(查询任务进度、获取seed)扣除费用 */
|
||||
public final static double MJ_COST_TYPE3 = 0.0;
|
||||
|
||||
/** 默认账户余额 */
|
||||
public final static double USER_BALANCE = 5;
|
||||
|
||||
}
|
||||
|
||||
@@ -22,16 +22,16 @@ public class ChatRequest {
|
||||
@NotEmpty(message = "对话消息不能为空")
|
||||
List<Message> messages;
|
||||
|
||||
List<Content> content;
|
||||
List<Content> imageContent;
|
||||
|
||||
private String prompt;
|
||||
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 需要识别的图片地址
|
||||
* 知识库id
|
||||
*/
|
||||
private String imgurl;
|
||||
private String kid;
|
||||
|
||||
/**
|
||||
* gpt的默认设置
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.xmzs.common.chat.domain.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class RoleRequest {
|
||||
|
||||
/**
|
||||
* 角色名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 角色描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 音频地址
|
||||
*/
|
||||
private String prompt;
|
||||
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
|
||||
private String preProcess;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.xmzs.common.chat.domain.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class SimpleGenerateRequest {
|
||||
|
||||
/**
|
||||
* 要使用的模型ID (目前统一为reecho-neural-voice-001)
|
||||
*/
|
||||
private String model = "reecho-neural-voice-001";
|
||||
|
||||
/**
|
||||
* 多样性 (0-100,默认为97)
|
||||
*/
|
||||
private Integer randomness;
|
||||
|
||||
/**
|
||||
* 稳定性过滤 (0-100,默认为0)
|
||||
*/
|
||||
private Integer stability_boost;
|
||||
|
||||
/**
|
||||
* 角色ID
|
||||
*/
|
||||
private String voiceId;
|
||||
|
||||
/**
|
||||
* 要生成的文本内容
|
||||
*/
|
||||
private String text;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.xmzs.common.chat.domain.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class MetadataResponse {
|
||||
private String promptMP3StorageUrl;
|
||||
private String promptOriginAudioStorageUrl;
|
||||
private String description;
|
||||
private boolean preProcess;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.xmzs.common.chat.domain.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class RoleDataResponse {
|
||||
private String id;
|
||||
private String name;
|
||||
private String status;
|
||||
private String from;
|
||||
private String originId;
|
||||
private MetadataResponse metadata;
|
||||
private String createdAt;
|
||||
private String updatedAt;
|
||||
private String deletedAt;
|
||||
private String userId;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.xmzs.common.chat.domain.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class RoleResponse {
|
||||
private String status;
|
||||
private String message;
|
||||
private RoleDataResponse data;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xmzs.common.chat.domain.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class SimpleGenerateDataResponse {
|
||||
|
||||
/**
|
||||
* 本次生成的ID
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 本次生成结果的音频文件地址
|
||||
*/
|
||||
private String audio;
|
||||
|
||||
/**
|
||||
* 本次生成所消耗的点数
|
||||
*/
|
||||
private Integer credit_used;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.xmzs.common.chat.domain.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author WangLe
|
||||
*/
|
||||
@Data
|
||||
public class SimpleGenerateResponse {
|
||||
|
||||
/**
|
||||
* 状态码,失败时则为500
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 状态消息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 生成详情
|
||||
*/
|
||||
private SimpleGenerateDataResponse data;
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package com.xmzs.common.chat.entity.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import com.xmzs.common.chat.constant.OpenAIConst;
|
||||
import com.xmzs.common.chat.entity.chat.tool.Tools;
|
||||
import lombok.*;
|
||||
@@ -217,6 +216,23 @@ public class BaseChatCompletion implements Serializable {
|
||||
* gpt-4-0613,支持函数
|
||||
*/
|
||||
GPT_4_0125_PREVIEW("gpt-4-0125-preview"),
|
||||
|
||||
/**
|
||||
* GPT_4_ALL
|
||||
*/
|
||||
GPT_4_ALL("gpt-4-all"),
|
||||
|
||||
GPT_4_GIZMO("gpt-4-gizmo"),
|
||||
|
||||
NET("net"),
|
||||
|
||||
CLAUDE_3_SONNET("claude-3-sonnet-20240229"),
|
||||
|
||||
GEMINI_PRO("gemini-pro"),
|
||||
|
||||
STABLE_DIFFUSION("stable-diffusion"),
|
||||
|
||||
SUNO_V3("suno-v3"),
|
||||
;
|
||||
private final String name;
|
||||
}
|
||||
@@ -238,9 +254,10 @@ public class BaseChatCompletion implements Serializable {
|
||||
}
|
||||
|
||||
public static double getModelCost(String modelName) {
|
||||
return switch (modelName) {
|
||||
case "gpt-3.5-turbo-0613" -> OpenAIConst.GPT3_COST;
|
||||
default -> OpenAIConst.GPT4_COST;
|
||||
};
|
||||
if(modelName.startsWith("gpt-3.5")){
|
||||
return OpenAIConst.GPT3_COST;
|
||||
}else {
|
||||
return OpenAIConst.GPT4_COST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,20 @@ import java.io.Serializable;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class File implements Serializable {
|
||||
|
||||
private String id;
|
||||
private String object;
|
||||
// private String id;
|
||||
// private String object;
|
||||
// private long bytes;
|
||||
// private long created_at;
|
||||
// private String filename;
|
||||
// private String purpose;
|
||||
// private String status;
|
||||
// @JsonProperty("status_details")
|
||||
// private String statusDetails;
|
||||
|
||||
private long bytes;
|
||||
private long created_at;
|
||||
private String filename;
|
||||
private String purpose;
|
||||
private String status;
|
||||
@JsonProperty("status_details")
|
||||
private String statusDetails;
|
||||
private String id;
|
||||
private String object;
|
||||
private String url;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.xmzs.common.chat.entity.billing.Subscription;
|
||||
import com.xmzs.common.chat.entity.chat.BaseChatCompletion;
|
||||
import com.xmzs.common.chat.entity.chat.ChatCompletionResponse;
|
||||
import com.xmzs.common.chat.entity.chat.ChatCompletionWithPicture;
|
||||
import com.xmzs.common.chat.entity.files.UploadFileResponse;
|
||||
import com.xmzs.common.chat.entity.images.Image;
|
||||
import com.xmzs.common.chat.entity.images.ImageResponse;
|
||||
import com.xmzs.common.chat.entity.models.Model;
|
||||
@@ -231,6 +232,23 @@ public class OpenAiStreamClient {
|
||||
return chatCompletionResponse.blockingGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param purpose purpose
|
||||
* @param file 文件对象
|
||||
* @return UploadFileResponse
|
||||
*/
|
||||
public UploadFileResponse uploadFile(String purpose, java.io.File file) {
|
||||
// 创建 RequestBody,用于封装构建RequestBody
|
||||
RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
|
||||
MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("file", file.getName(), fileBody);
|
||||
|
||||
RequestBody purposeBody = RequestBody.create(MediaType.parse("multipart/form-data"), purpose);
|
||||
Single<UploadFileResponse> uploadFileResponse = this.openAiApi.uploadFile(multipartBody, purposeBody);
|
||||
return uploadFileResponse.blockingGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取openKey账户信息(近90天)
|
||||
*
|
||||
|
||||
@@ -1,50 +1,57 @@
|
||||
package com.xmzs.common.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 支付配置信息
|
||||
*
|
||||
* @author Admin
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "pay")
|
||||
public class PayConfig {
|
||||
|
||||
/**
|
||||
* 商户ID
|
||||
*/
|
||||
public static String pid = "xxx";
|
||||
private String pid;
|
||||
|
||||
/**
|
||||
* 接口地址
|
||||
*/
|
||||
public static String payUrl = "https://pay-cloud.vip/mapi.php";
|
||||
private String payUrl;
|
||||
|
||||
/**
|
||||
* 私钥
|
||||
*/
|
||||
public static String key = "xxx";
|
||||
private String key ;
|
||||
|
||||
/**
|
||||
* 服务器异步通知地址
|
||||
*/
|
||||
public static String notify_url = "https://www.pandarobot.chat/pay/returnUrl";
|
||||
private String notify_url;
|
||||
|
||||
/**
|
||||
* 页面跳转通知地址
|
||||
*/
|
||||
public static String return_url = "https://www.pandarobot.chat/pay/notifyUrl";
|
||||
private String return_url;
|
||||
|
||||
/**
|
||||
* 支付方式
|
||||
*/
|
||||
public static String type = "wxpay";
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
public static String device = "pc";
|
||||
private String device;
|
||||
|
||||
/**
|
||||
* 加密方式默认MD5
|
||||
*/
|
||||
public static String sign_type = "MD5";
|
||||
private String sign_type;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.xmzs.common.service.impl;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
|
||||
import com.xmzs.common.config.PayConfig;
|
||||
import com.xmzs.common.service.PayService;
|
||||
import com.xmzs.common.utils.MD5Util;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -15,28 +17,31 @@ import java.util.Map;
|
||||
* @author Admin
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayServiceImpl implements PayService {
|
||||
|
||||
private final PayConfig payConfig;
|
||||
@Override
|
||||
public String getPayUrl(String orderNo, String name, double money, String clientIp) {
|
||||
String out_trade_no = orderNo, sign = "";
|
||||
//封装请求参数
|
||||
String mdString = "clientip=" + clientIp + "&device=" + PayConfig.device + "&money=" + money + "&name=" + name + "&" +
|
||||
"notify_url=" + PayConfig.notify_url + "&out_trade_no=" + out_trade_no + "&pid=" + PayConfig.pid + "&return_url=" + PayConfig.return_url +
|
||||
"&type=" + PayConfig.type + PayConfig.key;
|
||||
String mdString = "clientip=" + clientIp + "&device=" + payConfig.getDevice() + "&money=" + money + "&name=" + name + "&" +
|
||||
"notify_url=" + payConfig.getNotify_url() + "&out_trade_no=" + out_trade_no + "&pid=" + payConfig.getPid() + "&return_url=" + payConfig.getReturn_url() +
|
||||
"&type=" + payConfig.getType() + payConfig.getKey();
|
||||
sign = MD5Util.GetMD5Code(mdString);
|
||||
Map<String, Object> map = new HashMap<>(10);
|
||||
map.put("clientip", clientIp);
|
||||
map.put("device", PayConfig.device);
|
||||
map.put("device", payConfig.getDevice());
|
||||
map.put("money", money);
|
||||
map.put("name", name);
|
||||
map.put("notify_url", PayConfig.notify_url);
|
||||
map.put("notify_url", payConfig.getNotify_url());
|
||||
map.put("out_trade_no", out_trade_no);
|
||||
map.put("pid", PayConfig.pid);
|
||||
map.put("return_url", PayConfig.return_url);
|
||||
map.put("sign_type", PayConfig.sign_type);
|
||||
map.put("type", PayConfig.type);
|
||||
map.put("pid", payConfig.getPid());
|
||||
map.put("return_url", payConfig.getReturn_url());
|
||||
map.put("sign_type", payConfig.getSign_type());
|
||||
map.put("type", payConfig.getType());
|
||||
map.put("sign", sign);
|
||||
String body = HttpUtil.post(PayConfig.payUrl, map);
|
||||
String body = HttpUtil.post(payConfig.getPayUrl(), map);
|
||||
JSONObject jsonObject = new JSONObject(body);
|
||||
return (String) jsonObject.get("qrcode");
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
<module>ruoyi-job</module>
|
||||
<module>ruoyi-midjourney</module>
|
||||
<module>ruoyi-system</module>
|
||||
<module>ruoyi-live</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -7,30 +7,30 @@ import com.xmzs.common.core.utils.ValidatorUtils;
|
||||
import com.xmzs.common.core.validate.AddGroup;
|
||||
import com.xmzs.common.core.validate.EditGroup;
|
||||
import com.xmzs.common.core.validate.QueryGroup;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import com.xmzs.common.idempotent.annotation.RepeatSubmit;
|
||||
import com.xmzs.common.mybatis.core.page.PageQuery;
|
||||
import com.xmzs.common.mybatis.core.page.TableDataInfo;
|
||||
import com.xmzs.common.excel.core.ExcelResult;
|
||||
import com.xmzs.common.excel.utils.ExcelUtil;
|
||||
import com.xmzs.common.idempotent.annotation.RepeatSubmit;
|
||||
import com.xmzs.common.log.annotation.Log;
|
||||
import com.xmzs.common.log.enums.BusinessType;
|
||||
import com.xmzs.common.mybatis.core.page.PageQuery;
|
||||
import com.xmzs.common.mybatis.core.page.TableDataInfo;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import com.xmzs.demo.domain.TestDemo;
|
||||
import com.xmzs.demo.domain.bo.TestDemoBo;
|
||||
import com.xmzs.demo.domain.bo.TestDemoImportVo;
|
||||
import com.xmzs.demo.domain.vo.TestDemoVo;
|
||||
import com.xmzs.demo.service.ITestDemoService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,13 +2,13 @@ package com.xmzs.demo.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.xmzs.common.excel.utils.ExcelUtil;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.xmzs.demo.controller;
|
||||
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.core.utils.MessageUtils;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -9,9 +11,6 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* 测试国际化
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.xmzs.demo.controller;
|
||||
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import com.xmzs.common.sensitive.annotation.Sensitive;
|
||||
import com.xmzs.common.sensitive.core.SensitiveStrategy;
|
||||
import lombok.Data;
|
||||
import com.xmzs.common.sensitive.core.SensitiveService;
|
||||
import com.xmzs.common.sensitive.core.SensitiveStrategy;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -5,21 +5,21 @@ import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.core.validate.AddGroup;
|
||||
import com.xmzs.common.core.validate.EditGroup;
|
||||
import com.xmzs.common.core.validate.QueryGroup;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import com.xmzs.common.excel.utils.ExcelUtil;
|
||||
import com.xmzs.common.idempotent.annotation.RepeatSubmit;
|
||||
import com.xmzs.common.log.annotation.Log;
|
||||
import com.xmzs.common.log.enums.BusinessType;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import com.xmzs.demo.domain.bo.TestTreeBo;
|
||||
import com.xmzs.demo.domain.vo.TestTreeVo;
|
||||
import com.xmzs.demo.service.ITestTreeService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -5,11 +5,10 @@ import com.xmzs.common.core.validate.EditGroup;
|
||||
import com.xmzs.common.mybatis.core.domain.BaseEntity;
|
||||
import com.xmzs.demo.domain.TestDemo;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 测试单表业务对象 test_demo
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.xmzs.demo.domain.bo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 测试单表业务对象 test_demo
|
||||
|
||||
@@ -4,19 +4,19 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.xmzs.common.core.domain.R;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import com.xmzs.common.mybatis.core.page.PageQuery;
|
||||
import com.xmzs.common.mybatis.core.page.TableDataInfo;
|
||||
import com.xmzs.common.log.annotation.Log;
|
||||
import com.xmzs.common.log.enums.BusinessType;
|
||||
import com.xmzs.common.mybatis.core.page.PageQuery;
|
||||
import com.xmzs.common.mybatis.core.page.TableDataInfo;
|
||||
import com.xmzs.common.web.core.BaseController;
|
||||
import com.xmzs.generator.domain.GenTable;
|
||||
import com.xmzs.generator.domain.GenTableColumn;
|
||||
import com.xmzs.generator.service.IGenTableService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -6,12 +6,11 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.xmzs.common.core.utils.StringUtils;
|
||||
import com.xmzs.common.mybatis.core.domain.BaseEntity;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 代码生成业务字段表 gen_table_column
|
||||
*
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.xmzs.common.core.constant.Constants;
|
||||
import com.xmzs.generator.constant.GenConstants;
|
||||
import com.xmzs.common.core.exception.ServiceException;
|
||||
import com.xmzs.common.core.utils.StreamUtils;
|
||||
import com.xmzs.common.core.utils.StringUtils;
|
||||
@@ -20,6 +19,7 @@ import com.xmzs.common.json.utils.JsonUtils;
|
||||
import com.xmzs.common.mybatis.core.page.PageQuery;
|
||||
import com.xmzs.common.mybatis.core.page.TableDataInfo;
|
||||
import com.xmzs.common.satoken.utils.LoginHelper;
|
||||
import com.xmzs.generator.constant.GenConstants;
|
||||
import com.xmzs.generator.domain.GenTable;
|
||||
import com.xmzs.generator.domain.GenTableColumn;
|
||||
import com.xmzs.generator.mapper.GenTableColumnMapper;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.xmzs.generator.util;
|
||||
|
||||
import com.xmzs.generator.constant.GenConstants;
|
||||
import com.xmzs.common.core.utils.StringUtils;
|
||||
import com.xmzs.common.satoken.utils.LoginHelper;
|
||||
import com.xmzs.generator.config.GenConfig;
|
||||
import com.xmzs.generator.constant.GenConstants;
|
||||
import com.xmzs.generator.domain.GenTable;
|
||||
import com.xmzs.generator.domain.GenTableColumn;
|
||||
import lombok.AccessLevel;
|
||||
|
||||
@@ -3,11 +3,11 @@ package com.xmzs.generator.util;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import com.xmzs.generator.constant.GenConstants;
|
||||
import com.xmzs.common.core.utils.DateUtils;
|
||||
import com.xmzs.common.core.utils.StringUtils;
|
||||
import com.xmzs.common.json.utils.JsonUtils;
|
||||
import com.xmzs.common.mybatis.helper.DataBaseHelper;
|
||||
import com.xmzs.generator.constant.GenConstants;
|
||||
import com.xmzs.generator.domain.GenTable;
|
||||
import com.xmzs.generator.domain.GenTableColumn;
|
||||
import lombok.AccessLevel;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { ${BusinessName}VO, ${BusinessName}Form, ${BusinessName}Query } from '@/api/${moduleName}/${businessName}/types';
|
||||
import {AxiosPromise} from 'axios';
|
||||
import {${BusinessName}Form, ${BusinessName}Query, ${BusinessName}VO} from '@/api/';
|
||||
|
||||
/**
|
||||
* 查询${functionName}列表
|
||||
|
||||
@@ -258,12 +258,19 @@
|
||||
</template>
|
||||
|
||||
<script setup name="${BusinessName}" lang="ts">
|
||||
import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from '@/api/${moduleName}/${businessName}';
|
||||
import { ${BusinessName}VO, ${BusinessName}Query, ${BusinessName}Form } from '@/api/${moduleName}/${businessName}/types';
|
||||
import { ComponentInternalInstance } from 'vue';
|
||||
import { ElForm } from 'element-plus';
|
||||
import {
|
||||
add${BusinessName},
|
||||
${BusinessName}Form,
|
||||
get${BusinessName},
|
||||
list${BusinessName},
|
||||
${BusinessName}Query,
|
||||
update${BusinessName},
|
||||
${BusinessName}VO
|
||||
} from '@/api/';
|
||||
import {ComponentInternalInstance} from 'vue';
|
||||
import {ElForm} from 'element-plus';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
#if(${dicts} != '')
|
||||
#set($dictsNoSymbol=$dicts.replace("'", ""))
|
||||
const { ${dictsNoSymbol} } = toRefs<any>(proxy?.useDict(${dicts}));
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<!--
|
||||
~ 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-client-commons</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>live-chat-client-commons-base</artifactId>
|
||||
<name>ordinaryroad-live-chat-client-commons-base</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.constant;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public class Constants {
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.exception;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/5
|
||||
*/
|
||||
public class BaseException extends RuntimeException {
|
||||
|
||||
public BaseException() {
|
||||
}
|
||||
|
||||
public BaseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BaseException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public BaseException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public BaseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 连接回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public interface IBaseConnectionListener<T> {
|
||||
|
||||
/**
|
||||
* 连接建立成功
|
||||
*/
|
||||
default void onConnected(T t) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接建立失败
|
||||
*
|
||||
* @param t
|
||||
*/
|
||||
default void onConnectFailed(T t) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接断开
|
||||
*
|
||||
* @param t
|
||||
*/
|
||||
default void onDisconnected(T t) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.listener;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Base消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public interface IBaseMsgListener<T, CmdEnum extends Enum<CmdEnum>> {
|
||||
|
||||
/**
|
||||
* 收到消息(所有消息)
|
||||
*
|
||||
* @param msg IMsg
|
||||
*/
|
||||
default void onMsg(T t, IMsg msg) {
|
||||
this.onMsg(msg);
|
||||
}
|
||||
|
||||
default void onMsg(IMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到cmd消息(所有cmd)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
*/
|
||||
default void onCmdMsg(T t, CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
default void onCmdMsg(CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到其他cmd消息(存在Enum,但Listener没有对应的回调)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
*/
|
||||
default void onOtherCmdMsg(T t, CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onOtherCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
default void onOtherCmdMsg(CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到未知cmd消息
|
||||
*
|
||||
* @param cmdString 实际收到的cmd字符串
|
||||
* @param msg BaseMsg
|
||||
*/
|
||||
default void onUnknownCmd(T t, String cmdString, IMsg msg) {
|
||||
this.onUnknownCmd(cmdString, msg);
|
||||
}
|
||||
|
||||
default void onUnknownCmd(String cmdString, IMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到cmd消息(所有cmd)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
* @deprecated use {@link #onCmdMsg(T, Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onCmdMsg(T t, CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #onCmdMsg(Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onCmdMsg(CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到其他cmd消息(存在Enum,但Listener没有对应的回调)
|
||||
*
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseCmdMsg
|
||||
* @deprecated use {@link #onOtherCmdMsg(T, Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onOtherCmdMsg(T t, CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
this.onOtherCmdMsg(cmd, cmdMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #onOtherCmdMsg(Enum, ICmdMsg)}
|
||||
*/
|
||||
default void onOtherCmdMsg(CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到未知cmd消息
|
||||
*
|
||||
* @param cmdString 实际收到的cmd字符串
|
||||
* @param msg BaseMsg
|
||||
* @deprecated use {@link #onUnknownCmd(T, String, IMsg)}
|
||||
*/
|
||||
default void onUnknownCmd(T t, String cmdString, BaseMsg msg) {
|
||||
this.onUnknownCmd(cmdString, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #onUnknownCmd(String, IMsg)}
|
||||
*/
|
||||
default void onUnknownCmd(String cmdString, BaseMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 弹幕消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @since 0.0.6
|
||||
*/
|
||||
public interface IDanmuMsgListener<T, DanmuMsg> {
|
||||
|
||||
/**
|
||||
* 收到弹幕
|
||||
*/
|
||||
default void onDanmuMsg(T t, DanmuMsg msg) {
|
||||
this.onDanmuMsg(msg);
|
||||
}
|
||||
|
||||
default void onDanmuMsg(DanmuMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 进入房间消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/12/14
|
||||
* @since 0.0.16
|
||||
*/
|
||||
public interface IEnterRoomMsgListener<T, EnterRoomMsg> {
|
||||
|
||||
/**
|
||||
* 用户进入房间
|
||||
*/
|
||||
default void onEnterRoomMsg(T t, EnterRoomMsg msg) {
|
||||
this.onEnterRoomMsg(msg);
|
||||
}
|
||||
|
||||
default void onEnterRoomMsg(EnterRoomMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 礼物消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @since 0.0.8
|
||||
*/
|
||||
public interface IGiftMsgListener<T, GiftMsg> {
|
||||
|
||||
|
||||
/**
|
||||
* 收到礼物
|
||||
*/
|
||||
default void onGiftMsg(T t, GiftMsg msg) {
|
||||
this.onGiftMsg(msg);
|
||||
}
|
||||
|
||||
default void onGiftMsg(GiftMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 点赞消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface ILikeMsgListener<T, LikeMsg> {
|
||||
|
||||
/**
|
||||
* 收到点赞
|
||||
*/
|
||||
default void onLikeMsg(T t, LikeMsg msg) {
|
||||
this.onLikeMsg(msg);
|
||||
}
|
||||
|
||||
default void onLikeMsg(LikeMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.listener;
|
||||
|
||||
|
||||
/**
|
||||
* 醒目留言消息回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/9/24
|
||||
* @since 0.0.11
|
||||
*/
|
||||
public interface ISuperChatMsgListener<T, SuperChatMsg> {
|
||||
|
||||
/**
|
||||
* 收到醒目留言
|
||||
*/
|
||||
default void onSuperChatMsg(T t, SuperChatMsg msg) {
|
||||
this.onSuperChatMsg(msg);
|
||||
}
|
||||
|
||||
default void onSuperChatMsg(SuperChatMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public abstract class BaseCmdMsg<CmdEnum extends Enum<CmdEnum>> extends BaseMsg
|
||||
implements ICmdMsg<CmdEnum> {
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public abstract class BaseMsg implements IMsg {
|
||||
|
||||
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
|
||||
/**
|
||||
* 未知属性都放在这
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return OBJECT_MAPPER.writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/10/2
|
||||
*/
|
||||
public interface ICmdMsg<CmdEnum extends Enum<CmdEnum>> extends IMsg {
|
||||
|
||||
String getCmd();
|
||||
|
||||
void setCmd(String cmd);
|
||||
|
||||
CmdEnum getCmdEnum();
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
public interface IDanmuMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
String getBadgeName();
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
byte getBadgeLevel();
|
||||
|
||||
/**
|
||||
* 弹幕发送者id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 弹幕发送者用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 弹幕发送者头像地址
|
||||
*
|
||||
* @since 0.0.11
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹幕内容
|
||||
*/
|
||||
String getContent();
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
/**
|
||||
* 入房消息
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/12/26
|
||||
* @since 0.0.16
|
||||
*/
|
||||
public interface IEnterRoomMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
String getBadgeName();
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
byte getBadgeLevel();
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 头像地址
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
public interface IGiftMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
default String getBadgeName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
default byte getBadgeLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送方id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 发送方用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 发送方头像地址
|
||||
*
|
||||
* @since 0.0.11
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼物名称
|
||||
*/
|
||||
String getGiftName();
|
||||
|
||||
/**
|
||||
* 礼物图像地址
|
||||
*/
|
||||
String getGiftImg();
|
||||
|
||||
/**
|
||||
* 礼物id
|
||||
*/
|
||||
String getGiftId();
|
||||
|
||||
/**
|
||||
* 礼物数量
|
||||
*/
|
||||
int getGiftCount();
|
||||
|
||||
/**
|
||||
* 单个礼物价格
|
||||
*/
|
||||
int getGiftPrice();
|
||||
|
||||
/**
|
||||
* 接收方id
|
||||
*/
|
||||
String getReceiveUid();
|
||||
|
||||
/**
|
||||
* 接收方用户名
|
||||
*/
|
||||
String getReceiveUsername();
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2024/1/31
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface ILikeMsg extends IMsg {
|
||||
|
||||
/**
|
||||
* 粉丝牌名称
|
||||
*/
|
||||
default String getBadgeName(){
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 粉丝牌等级
|
||||
*/
|
||||
default byte getBadgeLevel(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞者id
|
||||
*/
|
||||
String getUid();
|
||||
|
||||
/**
|
||||
* 点赞者用户名
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* 点赞者头像地址
|
||||
*/
|
||||
default String getUserAvatar() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞数
|
||||
*/
|
||||
default int getClickCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public interface IMsg extends Serializable {
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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.commons.base.msg;
|
||||
|
||||
/**
|
||||
* 醒目留言
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/9/22
|
||||
*/
|
||||
public interface ISuperChatMsg extends IDanmuMsg {
|
||||
|
||||
/**
|
||||
* 醒目留言持续时间,单位秒
|
||||
*/
|
||||
int getDuration();
|
||||
|
||||
@Override
|
||||
default String getBadgeName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
default byte getBadgeLevel() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<!--
|
||||
~ 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-client-commons</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-commons-client</artifactId>
|
||||
<name>live-chat-client-commons-client</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-base</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-util</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* 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.commons.client;
|
||||
|
||||
import lombok.Getter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.config.BaseLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.enums.ClientStatusEnums;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public abstract class BaseLiveChatClient<
|
||||
Config extends BaseLiveChatClientConfig,
|
||||
MsgListener extends IBaseMsgListener<?, ?>
|
||||
> implements IBaseLiveChatClient<MsgListener> {
|
||||
|
||||
private final Config config;
|
||||
@Getter
|
||||
private volatile ClientStatusEnums status = ClientStatusEnums.NEW;
|
||||
protected PropertyChangeSupport statusChangeSupport = new PropertyChangeSupport(status);
|
||||
protected volatile boolean cancelReconnect = false;
|
||||
protected final List<MsgListener> msgListeners = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
protected BaseLiveChatClient(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public Config getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(Runnable success) {
|
||||
this.connect(success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
this.connect(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(boolean cancelReconnect) {
|
||||
this.cancelReconnect = cancelReconnect;
|
||||
this.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg) {
|
||||
this.send(msg, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg, Runnable success) {
|
||||
this.send(msg, success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg, Consumer<Throwable> failed) {
|
||||
this.send(msg, null, failed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu) {
|
||||
this.sendDanmu(danmu, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Runnable success) {
|
||||
this.sendDanmu(danmu, success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Consumer<Throwable> failed) {
|
||||
this.sendDanmu(danmu, null, failed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count) {
|
||||
this.clickLike(count, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Runnable success) {
|
||||
this.clickLike(count, success, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Consumer<Throwable> failed) {
|
||||
this.clickLike(count, null, failed);
|
||||
}
|
||||
|
||||
protected abstract void tryReconnect();
|
||||
|
||||
protected abstract String getWebSocketUriString();
|
||||
|
||||
/**
|
||||
* 判断是否处于某个状态,或者处于后续状态
|
||||
*
|
||||
* @param status {@link ClientStatusEnums}
|
||||
* @return false: 还没有到达该状态
|
||||
*/
|
||||
protected boolean checkStatus(ClientStatusEnums status) {
|
||||
return this.status.getCode() >= Objects.requireNonNull(status).getCode();
|
||||
}
|
||||
|
||||
protected void setStatus(ClientStatusEnums status) {
|
||||
ClientStatusEnums oldStatus = this.status;
|
||||
if (oldStatus != status) {
|
||||
this.status = status;
|
||||
this.statusChangeSupport.firePropertyChange("status", oldStatus, status);
|
||||
}
|
||||
}
|
||||
|
||||
public void addStatusChangeListener(PropertyChangeListener listener) {
|
||||
this.statusChangeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removeStatusChangeListener(PropertyChangeListener listener) {
|
||||
this.statusChangeSupport.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
for (PropertyChangeListener propertyChangeListener : this.statusChangeSupport.getPropertyChangeListeners()) {
|
||||
this.statusChangeSupport.removePropertyChangeListener(propertyChangeListener);
|
||||
}
|
||||
this.msgListeners.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addMsgListener(MsgListener msgListener) {
|
||||
if (msgListener == null) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.add(msgListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addMsgListeners(List<MsgListener> msgListeners) {
|
||||
if (msgListeners == null || msgListeners.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.addAll(msgListeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMsgListener(MsgListener msgListener) {
|
||||
if (msgListener == null) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.remove(msgListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeMsgListeners(List<MsgListener> msgListeners) {
|
||||
if (msgListeners == null || msgListeners.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return this.msgListeners.removeAll(msgListeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllMsgListeners() {
|
||||
this.msgListeners.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* 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.commons.client;
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/5
|
||||
*/
|
||||
public interface IBaseLiveChatClient<MsgListener extends IBaseMsgListener<?, ?>> {
|
||||
|
||||
void init();
|
||||
|
||||
boolean addMsgListener(MsgListener msgListener);
|
||||
|
||||
boolean addMsgListeners(List<MsgListener> msgListeners);
|
||||
|
||||
boolean removeMsgListener(MsgListener msgListener);
|
||||
|
||||
boolean removeMsgListeners(List<MsgListener> msgListeners);
|
||||
|
||||
void removeAllMsgListeners();
|
||||
|
||||
void connect(Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
void connect(Runnable success);
|
||||
|
||||
void connect();
|
||||
|
||||
/**
|
||||
* 手动断开连接
|
||||
*
|
||||
* @param cancelReconnect 取消本次的自动重连(如果启用自动重连)
|
||||
*/
|
||||
void disconnect(boolean cancelReconnect);
|
||||
|
||||
void disconnect();
|
||||
|
||||
void destroy();
|
||||
|
||||
void send(Object msg);
|
||||
|
||||
void send(Object msg, Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
void send(Object msg, Runnable success);
|
||||
|
||||
void send(Object msg, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu, Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu, Runnable success);
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param danmu 弹幕内容
|
||||
* @since 0.0.6
|
||||
*/
|
||||
void sendDanmu(Object danmu, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count, Runnable success, Consumer<Throwable> failed);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count, Runnable success);
|
||||
|
||||
/**
|
||||
* 为直播间点赞
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
void clickLike(int count, Consumer<Throwable> failed);
|
||||
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* 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.commons.client.config;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
|
||||
/**
|
||||
* 直播间弹幕客户端配置
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public abstract class BaseLiveChatClientConfig {
|
||||
|
||||
protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
|
||||
public static final long DEFAULT_HEARTBEAT_INITIAL_DELAY = 15;
|
||||
public static final long DEFAULT_HEARTBEAT_PERIOD = 25;
|
||||
public static final long DEFAULT_MIN_SEND_DANMU_PERIOD = 3000L;
|
||||
|
||||
private String websocketUri;
|
||||
|
||||
/**
|
||||
* 浏览器中的Cookie
|
||||
*/
|
||||
private String cookie;
|
||||
|
||||
/**
|
||||
* 直播间id
|
||||
*/
|
||||
private Object roomId;
|
||||
|
||||
/**
|
||||
* 是否启用自动重连
|
||||
*/
|
||||
@Builder.Default
|
||||
private boolean autoReconnect = Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* 重试延迟时间(秒),默认5s后重试
|
||||
*/
|
||||
@Builder.Default
|
||||
private int reconnectDelay = 5;
|
||||
|
||||
/**
|
||||
* 首次发送心跳包的延迟时间(秒)
|
||||
*/
|
||||
@Builder.Default
|
||||
private long heartbeatInitialDelay = DEFAULT_HEARTBEAT_INITIAL_DELAY;
|
||||
|
||||
/**
|
||||
* 心跳包发送周期(秒)
|
||||
*/
|
||||
@Builder.Default
|
||||
private long heartbeatPeriod = DEFAULT_HEARTBEAT_PERIOD;
|
||||
|
||||
/**
|
||||
* 最小发送弹幕时间间隔(毫秒)
|
||||
*/
|
||||
@Builder.Default
|
||||
private long minSendDanmuPeriod = DEFAULT_MIN_SEND_DANMU_PERIOD;
|
||||
|
||||
public void setCookie(String cookie) {
|
||||
String oldValue = this.cookie;
|
||||
this.cookie = cookie;
|
||||
this.propertyChangeSupport.firePropertyChange("cookie", oldValue, cookie);
|
||||
}
|
||||
|
||||
public void setRoomId(Object roomId) {
|
||||
if (!(roomId instanceof Number || roomId instanceof String)) {
|
||||
throw new BaseException("房间ID仅支持数字或字符串,所传参数类型:" + roomId.getClass() + "值:" + roomId);
|
||||
}
|
||||
Object oldValue = this.roomId;
|
||||
this.roomId = roomId;
|
||||
this.propertyChangeSupport.firePropertyChange("roomId", oldValue, roomId);
|
||||
}
|
||||
|
||||
public void setWebsocketUri(String websocketUri) {
|
||||
String oldValue = this.websocketUri;
|
||||
this.websocketUri = websocketUri;
|
||||
this.propertyChangeSupport.firePropertyChange("websocketUri", oldValue, websocketUri);
|
||||
}
|
||||
|
||||
public void setMinSendDanmuPeriod(long minSendDanmuPeriod) {
|
||||
long oldValue = this.minSendDanmuPeriod;
|
||||
this.minSendDanmuPeriod = minSendDanmuPeriod;
|
||||
this.propertyChangeSupport.firePropertyChange("minSendDanmuPeriod", oldValue, minSendDanmuPeriod);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.propertyChangeSupport.removePropertyChangeListener(listener);
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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.commons.client.enums;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
public enum ClientStatusEnums {
|
||||
/**
|
||||
* 新创建
|
||||
*/
|
||||
NEW(0),
|
||||
|
||||
/**
|
||||
* 已初始化
|
||||
*/
|
||||
INITIALIZED(1),
|
||||
|
||||
/**
|
||||
* 连接中
|
||||
*/
|
||||
CONNECTING(100),
|
||||
|
||||
/**
|
||||
* 重新连接中
|
||||
*/
|
||||
RECONNECTING(101),
|
||||
|
||||
/**
|
||||
* 已连接
|
||||
*/
|
||||
CONNECTED(200),
|
||||
|
||||
/**
|
||||
* 连接失败
|
||||
*/
|
||||
CONNECT_FAILED(401),
|
||||
|
||||
/**
|
||||
* 已断开连接
|
||||
*/
|
||||
DISCONNECTED(400),
|
||||
|
||||
/**
|
||||
* 已销毁
|
||||
*/
|
||||
DESTROYED(-1),
|
||||
;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
ClientStatusEnums(int order) {
|
||||
this.code = order;
|
||||
}
|
||||
|
||||
private final int code;
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<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-client-commons</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-commons-util</artifactId>
|
||||
<name>live-chat-client-commons-util</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* 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.commons.util;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
public class OrLiveChatCookieUtil {
|
||||
|
||||
public static String toString(List<HttpCookie> cookies) {
|
||||
if (CollUtil.isEmpty(cookies)) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
return cookies.stream().map(httpCookie -> {
|
||||
httpCookie.setVersion(0);
|
||||
return httpCookie.toString();
|
||||
}).collect(Collectors.joining("; "));
|
||||
}
|
||||
|
||||
public static Map<String, String> parseCookieString(String cookies) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (StrUtil.isNotBlank(cookies) && !StrUtil.isNullOrUndefined(cookies)) {
|
||||
try {
|
||||
String[] split = cookies.split("; ");
|
||||
for (String s : split) {
|
||||
String[] split1 = s.split("=");
|
||||
map.put(split1[0], split1[1]);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("cookie解析失败 " + cookies, e);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static String getCookieByName(Map<String, String> cookieMap, String name, Supplier<String> supplier) {
|
||||
String str = MapUtil.getStr(cookieMap, name);
|
||||
return str == null ? supplier.get() : str;
|
||||
}
|
||||
|
||||
public static String getCookieByName(String cookie, String name, Supplier<String> supplier) {
|
||||
String str = MapUtil.getStr(parseCookieString(cookie), name);
|
||||
return str == null ? supplier.get() : str;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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.commons.util;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/12/2
|
||||
*/
|
||||
public class OrLiveChatNumberUtil extends NumberUtil {
|
||||
|
||||
public static long parseLong(Object object){
|
||||
return NumberUtil.parseLong(StrUtil.toStringOrNull(object));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.commons.util;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/28
|
||||
*/
|
||||
public class OrLiveChatReflectUtil extends ReflectUtil {
|
||||
|
||||
public static Method getGetterMethod(Class<?> objectClass, String key) {
|
||||
Method method;
|
||||
if (key.startsWith("is")) {
|
||||
method = ReflectUtil.getMethodByNameIgnoreCase(objectClass, key);
|
||||
if (method == null) {
|
||||
ReflectUtil.getMethodByNameIgnoreCase(objectClass, "get" + key);
|
||||
}
|
||||
} else {
|
||||
method = ReflectUtil.getMethodByNameIgnoreCase(objectClass, "get" + key);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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.commons.util;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/7
|
||||
*/
|
||||
public class OrLocalDateTimeUtil extends LocalDateTimeUtil {
|
||||
|
||||
public static ZoneId ZONE_ID_CTT = ZoneId.of(ZoneId.SHORT_IDS.get("CTT"));
|
||||
|
||||
/**
|
||||
* 获取中国标准时间的当前时间戳(毫秒)
|
||||
*/
|
||||
public static long zonedCurrentTimeMillis() {
|
||||
ZonedDateTime now = ZonedDateTime.now(ZONE_ID_CTT);
|
||||
return now.toEpochSecond() * 1000 + now.getNano() / 1_000_000;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取中国标准时间的当前时间戳(秒)
|
||||
*/
|
||||
public static long zonedCurrentTimeSecs() {
|
||||
return ZonedDateTime.now(ZONE_ID_CTT).toEpochSecond();
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<!--
|
||||
~ 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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>ruoyi-live</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<artifactId>live-chat-client-commons</artifactId>
|
||||
|
||||
<modules>
|
||||
<module>live-chat-client-commons-base</module>
|
||||
<module>live-chat-client-commons-util</module>
|
||||
<module>live-chat-client-commons-client</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -1,55 +0,0 @@
|
||||
<!--
|
||||
~ 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-client-servers</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-servers-netty-client</artifactId>
|
||||
<name>live-chat-client-servers-netty</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-servers-netty</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
* 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.servers.netty.client.base;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.BaseLiveChatClient;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.enums.ClientStatusEnums;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.config.BaseNettyClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseConnectionHandler;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseNettyClient
|
||||
<Config extends BaseNettyClientConfig,
|
||||
CmdEnum extends Enum<CmdEnum>,
|
||||
Msg extends IMsg,
|
||||
MsgListener extends IBaseMsgListener<BinaryFrameHandler, CmdEnum>,
|
||||
ConnectionHandler extends BaseConnectionHandler<ConnectionHandler>,
|
||||
BinaryFrameHandler extends BaseBinaryFrameHandler<BinaryFrameHandler, CmdEnum, Msg, MsgListener>
|
||||
>
|
||||
extends BaseLiveChatClient<Config, MsgListener> {
|
||||
|
||||
@Getter
|
||||
private final EventLoopGroup workerGroup;
|
||||
@Getter
|
||||
private final Bootstrap bootstrap = new Bootstrap();
|
||||
private BinaryFrameHandler binaryFrameHandler;
|
||||
private ConnectionHandler connectionHandler;
|
||||
private IBaseConnectionListener<ConnectionHandler> connectionListener;
|
||||
private Channel channel;
|
||||
@Getter
|
||||
private URI websocketUri;
|
||||
protected IBaseConnectionListener<ConnectionHandler> clientConnectionListener;
|
||||
/**
|
||||
* 控制弹幕发送频率
|
||||
*/
|
||||
private volatile long lastSendDanmuTimeInMillis;
|
||||
|
||||
public abstract ConnectionHandler initConnectionHandler(IBaseConnectionListener<ConnectionHandler> clientConnectionListener);
|
||||
|
||||
public abstract BinaryFrameHandler initBinaryFrameHandler();
|
||||
|
||||
protected BaseNettyClient(Config config, EventLoopGroup workerGroup, IBaseConnectionListener<ConnectionHandler> connectionListener) {
|
||||
super(config);
|
||||
this.workerGroup = workerGroup;
|
||||
this.connectionListener = connectionListener;
|
||||
}
|
||||
|
||||
public void onConnected(ConnectionHandler connectionHandler) {
|
||||
this.setStatus(ClientStatusEnums.CONNECTED);
|
||||
if (this.connectionListener != null) {
|
||||
this.connectionListener.onConnected(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public void onConnectFailed(ConnectionHandler connectionHandler) {
|
||||
this.setStatus(ClientStatusEnums.CONNECT_FAILED);
|
||||
tryReconnect();
|
||||
if (this.connectionListener != null) {
|
||||
this.connectionListener.onConnectFailed(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisconnected(ConnectionHandler connectionHandler) {
|
||||
this.setStatus(ClientStatusEnums.DISCONNECTED);
|
||||
tryReconnect();
|
||||
if (this.connectionListener != null) {
|
||||
this.connectionListener.onDisconnected(connectionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
if (checkStatus(ClientStatusEnums.INITIALIZED)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.websocketUri = new URI(getWebSocketUriString());
|
||||
SslContext sslCtx = SslContextBuilder.forClient().build();
|
||||
|
||||
this.clientConnectionListener = new IBaseConnectionListener<ConnectionHandler>() {
|
||||
@Override
|
||||
public void onConnected(ConnectionHandler connectionHandler) {
|
||||
BaseNettyClient.this.onConnected(connectionHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectFailed(ConnectionHandler connectionHandler) {
|
||||
BaseNettyClient.this.onConnectFailed(connectionHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected(ConnectionHandler connectionHandler) {
|
||||
BaseNettyClient.this.onDisconnected(connectionHandler);
|
||||
}
|
||||
};
|
||||
this.binaryFrameHandler = this.initBinaryFrameHandler();
|
||||
this.connectionHandler = this.initConnectionHandler(this.clientConnectionListener);
|
||||
|
||||
this.bootstrap.group(this.workerGroup)
|
||||
// 创建Channel
|
||||
.channel(NioSocketChannel.class)
|
||||
.remoteAddress(this.websocketUri.getHost(), getInetPort())
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.SO_KEEPALIVE, true)
|
||||
// Channel配置
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) {
|
||||
// 责任链
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
|
||||
// 放到第一位 addFirst 支持wss链接服务端
|
||||
pipeline.addFirst(sslCtx.newHandler(ch.alloc(), BaseNettyClient.this.websocketUri.getHost(), getInetPort()));
|
||||
|
||||
// 添加一个http的编解码器
|
||||
pipeline.addLast(new HttpClientCodec());
|
||||
// 添加一个用于支持大数据流的支持
|
||||
pipeline.addLast(new ChunkedWriteHandler());
|
||||
// 添加一个聚合器,这个聚合器主要是将HttpMessage聚合成FullHttpRequest/Response
|
||||
pipeline.addLast(new HttpObjectAggregator(BaseNettyClient.this.getConfig().getAggregatorMaxContentLength()));
|
||||
|
||||
// 连接处理器
|
||||
pipeline.addLast(BaseNettyClient.this.connectionHandler);
|
||||
// 弹幕处理器
|
||||
pipeline.addLast(BaseNettyClient.this.binaryFrameHandler);
|
||||
}
|
||||
});
|
||||
this.setStatus(ClientStatusEnums.INITIALIZED);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new BaseException(e);
|
||||
} catch (SSLException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int getInetPort() {
|
||||
int port = this.websocketUri.getPort();
|
||||
return port == -1 ? "wss".equalsIgnoreCase(websocketUri.getScheme()) ? 443 : 80 : port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(Runnable success, Consumer<Throwable> failed) {
|
||||
if (this.cancelReconnect) {
|
||||
this.cancelReconnect = false;
|
||||
}
|
||||
if (!checkStatus(ClientStatusEnums.INITIALIZED)) {
|
||||
return;
|
||||
}
|
||||
if (getStatus() == ClientStatusEnums.CONNECTED) {
|
||||
return;
|
||||
}
|
||||
if (getStatus() != ClientStatusEnums.RECONNECTING) {
|
||||
this.setStatus(ClientStatusEnums.CONNECTING);
|
||||
}
|
||||
this.bootstrap.connect().addListener((ChannelFutureListener) connectFuture -> {
|
||||
if (connectFuture.isSuccess()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("连接建立成功!");
|
||||
}
|
||||
this.channel = connectFuture.channel();
|
||||
// 监听是否握手成功
|
||||
this.connectionHandler.getHandshakeFuture().addListener((ChannelFutureListener) handshakeFuture -> {
|
||||
try {
|
||||
connectionHandler.sendAuthRequest(channel);
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("认证包发送失败,断开连接", e);
|
||||
this.disconnect();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.error("连接建立失败", connectFuture.cause());
|
||||
this.onConnectFailed(this.connectionHandler);
|
||||
if (failed != null) {
|
||||
failed.accept(connectFuture.cause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
if (this.channel == null) {
|
||||
return;
|
||||
}
|
||||
this.channel.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tryReconnect() {
|
||||
if (this.cancelReconnect) {
|
||||
this.cancelReconnect = false;
|
||||
return;
|
||||
}
|
||||
if (!getConfig().isAutoReconnect()) {
|
||||
return;
|
||||
}
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("{}s后将重新连接 {}", getConfig().getReconnectDelay(), getConfig().getRoomId());
|
||||
}
|
||||
workerGroup.schedule(() -> {
|
||||
this.setStatus(ClientStatusEnums.RECONNECTING);
|
||||
this.connect();
|
||||
}, getConfig().getReconnectDelay(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object msg, Runnable success, Consumer<Throwable> failed) {
|
||||
ChannelFuture future = this.channel.writeAndFlush(msg);
|
||||
if (success != null || failed != null) {
|
||||
future.addListener((ChannelFutureListener) channelFuture -> {
|
||||
if (channelFuture.isSuccess()) {
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
} else {
|
||||
if (failed != null) {
|
||||
failed.accept(channelFuture.cause());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
// 销毁时不需要重连
|
||||
this.cancelReconnect = true;
|
||||
workerGroup.shutdownGracefully().addListener(future -> {
|
||||
if (future.isSuccess()) {
|
||||
this.setStatus(ClientStatusEnums.DESTROYED);
|
||||
} else {
|
||||
throw new BaseException("client销毁失败", future.cause());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getWebSocketUriString() {
|
||||
return getConfig().getWebsocketUri();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setStatus(ClientStatusEnums status) {
|
||||
if (log.isDebugEnabled()) {
|
||||
if (getStatus() != status) {
|
||||
log.debug("{} 状态变化 {} => {}\n", getClass().getSimpleName(), getStatus(), status);
|
||||
}
|
||||
}
|
||||
super.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Runnable success, Consumer<Throwable> failed) {
|
||||
throw new BaseException("暂未支持该功能");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Runnable success, Consumer<Throwable> failed) {
|
||||
throw new BaseException("暂未支持该功能");
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕前判断是否可以发送
|
||||
*
|
||||
* @param checkConnected 是否检查Client连接状态
|
||||
*/
|
||||
protected boolean checkCanSendDanmu(boolean checkConnected) {
|
||||
if (checkConnected && getStatus() != ClientStatusEnums.CONNECTED) {
|
||||
throw new BaseException("连接未建立,无法发送弹幕");
|
||||
}
|
||||
if (System.currentTimeMillis() - this.lastSendDanmuTimeInMillis <= getConfig().getMinSendDanmuPeriod()) {
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("发送弹幕频率过快,忽略该次发送");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean checkCanSendDanmu() {
|
||||
return checkCanSendDanmu(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕后调用该方法
|
||||
*/
|
||||
protected void finishSendDanmu() {
|
||||
this.lastSendDanmuTimeInMillis = System.currentTimeMillis();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("弹幕发送完成");
|
||||
}
|
||||
}
|
||||
|
||||
public void iteratorMsgListeners(Consumer<MsgListener> consumer) {
|
||||
binaryFrameHandler.iteratorMsgListeners(consumer);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.servers.netty.client.config;
|
||||
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import tech.ordinaryroad.live.chat.client.commons.client.config.BaseLiveChatClientConfig;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/8/26
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public abstract class BaseNettyClientConfig extends BaseLiveChatClientConfig {
|
||||
|
||||
/**
|
||||
* 聚合器允许的最大消息体长度,默认 64*1024 byte
|
||||
*
|
||||
* @see HttpObjectAggregator#HttpObjectAggregator(int)
|
||||
*/
|
||||
@Builder.Default
|
||||
private int aggregatorMaxContentLength = 64 * 1024;
|
||||
|
||||
/**
|
||||
* WebSocketClientHandshaker最大消息体长度,默认 64*1024 byte
|
||||
*
|
||||
* @see WebSocketClientHandshakerFactory#newHandshaker(URI, WebSocketVersion, String, boolean, HttpHeaders, int)
|
||||
*/
|
||||
@Builder.Default
|
||||
private int maxFramePayloadLength = 64 * 1024;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* 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.servers.netty.client.handler;
|
||||
|
||||
import lombok.Getter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IMsg;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.base.BaseNettyClient;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseBinaryFrameHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BaseClientBinaryFrameHandler
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/30
|
||||
*/
|
||||
public abstract class BaseNettyClientBinaryFrameHandler<
|
||||
Client extends BaseNettyClient<?, ?, ?, ?, ?, ?>,
|
||||
BinaryFrameHandler extends BaseBinaryFrameHandler<BinaryFrameHandler, CmdEnum, Msg, MsgListener>,
|
||||
CmdEnum extends Enum<CmdEnum>,
|
||||
Msg extends IMsg,
|
||||
MsgListener extends IBaseMsgListener<BinaryFrameHandler, CmdEnum>>
|
||||
extends BaseBinaryFrameHandler<BinaryFrameHandler, CmdEnum, Msg, MsgListener> {
|
||||
|
||||
@Getter
|
||||
protected final Client client;
|
||||
|
||||
public BaseNettyClientBinaryFrameHandler(List<MsgListener> msgListeners, Client client, long roomId) {
|
||||
super(msgListeners, roomId);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public BaseNettyClientBinaryFrameHandler(List<MsgListener> msgListeners, Client client) {
|
||||
super(msgListeners, client.getConfig().getRoomId());
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public BaseNettyClientBinaryFrameHandler(List<MsgListener> msgListeners, long roomId) {
|
||||
super(msgListeners, roomId);
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.servers.netty.client.handler;
|
||||
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import lombok.Getter;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.base.BaseNettyClient;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.handler.base.BaseConnectionHandler;
|
||||
|
||||
/**
|
||||
* BaseClientConnectionHandler
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/27
|
||||
*/
|
||||
public abstract class BaseNettyClientConnectionHandler<
|
||||
Client extends BaseNettyClient<?, ?, ?, ?, ?, ?>,
|
||||
ConnectionHandler extends BaseConnectionHandler<ConnectionHandler>>
|
||||
extends BaseConnectionHandler<ConnectionHandler> {
|
||||
|
||||
@Getter
|
||||
protected final Client client;
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, Client client, IBaseConnectionListener<ConnectionHandler> listener) {
|
||||
super(handshaker, listener);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, Client client) {
|
||||
this(handshaker, client, null);
|
||||
}
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, IBaseConnectionListener<ConnectionHandler> listener) {
|
||||
super(handshaker, listener);
|
||||
this.client = null;
|
||||
}
|
||||
|
||||
public BaseNettyClientConnectionHandler(WebSocketClientHandshaker handshaker, long roomId) {
|
||||
super(handshaker, null);
|
||||
this.client = null;
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<!--
|
||||
~ 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-client-servers</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-servers-netty</artifactId>
|
||||
<name>live-chat-client-servers-netty</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.xmzs</groupId>
|
||||
<artifactId>live-chat-client-commons-base</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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.servers.netty.frame.base;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
public abstract class BaseBinaryWebSocketFrame extends BinaryWebSocketFrame {
|
||||
|
||||
public BaseBinaryWebSocketFrame(ByteBuf byteBuf) {
|
||||
super(byteBuf);
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* 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.servers.netty.handler.base;
|
||||
|
||||
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseMsgListener;
|
||||
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 java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
* 消息处理器
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/1/4
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseBinaryFrameHandler<
|
||||
T extends BaseBinaryFrameHandler<?, ?, ?, ?>,
|
||||
CmdEnum extends Enum<CmdEnum>,
|
||||
Msg extends IMsg,
|
||||
MsgListener extends IBaseMsgListener<T, CmdEnum>
|
||||
> extends SimpleChannelInboundHandler<BinaryWebSocketFrame>
|
||||
implements IBaseMsgListener<T, CmdEnum> {
|
||||
|
||||
@Getter
|
||||
private final Object roomId;
|
||||
protected final List<MsgListener> msgListeners;
|
||||
|
||||
public BaseBinaryFrameHandler(List<MsgListener> msgListeners, Object roomId) {
|
||||
this.msgListeners = msgListeners;
|
||||
this.roomId = roomId;
|
||||
if (this.msgListeners == null || this.msgListeners.isEmpty()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("listener not set");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码收到的二进制流
|
||||
*
|
||||
* @param byteBuf ByteBuf
|
||||
* @return List<Msg>
|
||||
*/
|
||||
protected abstract List<Msg> decode(ByteBuf byteBuf);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void channelRead0(ChannelHandlerContext ctx, BinaryWebSocketFrame message) {
|
||||
ByteBuf byteBuf = message.content();
|
||||
List<Msg> msgList = this.decode(byteBuf);
|
||||
if (msgList == null || msgList.isEmpty()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("msgList is empty");
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (Msg msg : msgList) {
|
||||
this.onMsg((T) BaseBinaryFrameHandler.this, msg);
|
||||
if (msg instanceof ICmdMsg<?>) {
|
||||
ICmdMsg<?> cmdMsg = (ICmdMsg<?>) msg;
|
||||
Enum<?> cmdEnum = cmdMsg.getCmdEnum();
|
||||
if (cmdEnum == null) {
|
||||
this.onUnknownCmd((T) BaseBinaryFrameHandler.this, cmdMsg.getCmd(), cmdMsg);
|
||||
} else {
|
||||
this.onCmdMsg((T) BaseBinaryFrameHandler.this, (CmdEnum) cmdEnum, (ICmdMsg<CmdEnum>) cmdMsg);
|
||||
}
|
||||
}
|
||||
if (msg instanceof BaseCmdMsg<?>) {
|
||||
BaseCmdMsg<?> cmdMsg = (BaseCmdMsg<?>) msg;
|
||||
Enum<?> cmdEnum = cmdMsg.getCmdEnum();
|
||||
if (cmdEnum == null) {
|
||||
this.onUnknownCmd((T) BaseBinaryFrameHandler.this, cmdMsg.getCmd(), cmdMsg);
|
||||
} else {
|
||||
this.onCmdMsg((T) BaseBinaryFrameHandler.this, (CmdEnum) cmdEnum, (BaseCmdMsg<CmdEnum>) cmdMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (cause.getCause() instanceof UnrecognizedPropertyException) {
|
||||
log.error("缺少字段:{}", cause.getMessage());
|
||||
} else {
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsg(T t, IMsg msg) {
|
||||
IBaseMsgListener.super.onMsg(t, msg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onMsg(t, msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写该方法,判断CMD,或者调用{@link IBaseMsgListener#onOtherCmdMsg(Object, Enum, ICmdMsg)}
|
||||
*
|
||||
* @param t BaseBinaryFrameHandler
|
||||
* @param cmd CmdEnum
|
||||
* @param cmdMsg BaseMsg
|
||||
*/
|
||||
@Override
|
||||
public void onCmdMsg(T t, CmdEnum cmd, ICmdMsg<CmdEnum> cmdMsg) {
|
||||
IBaseMsgListener.super.onCmdMsg(t, cmd, cmdMsg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onCmdMsg(t, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnknownCmd(T t, String cmdString, IMsg msg) {
|
||||
IBaseMsgListener.super.onUnknownCmd(t, cmdString, msg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onUnknownCmd(t, cmdString, msg));
|
||||
}
|
||||
|
||||
@SuppressWarnings("ForLoopReplaceableByForEach")
|
||||
public void iteratorMsgListeners(Consumer<MsgListener> consumer) {
|
||||
if (msgListeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < msgListeners.size(); i++) {
|
||||
consumer.accept(msgListeners.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCmdMsg(T t, CmdEnum cmd, BaseCmdMsg<CmdEnum> cmdMsg) {
|
||||
IBaseMsgListener.super.onCmdMsg(t, cmd, cmdMsg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onCmdMsg(t, cmd, cmdMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnknownCmd(T t, String cmdString, BaseMsg msg) {
|
||||
IBaseMsgListener.super.onUnknownCmd(t, cmdString, msg);
|
||||
iteratorMsgListeners(msgListener -> msgListener.onUnknownCmd(t, cmdString, msg));
|
||||
}
|
||||
|
||||
public String getRoomIdAsString() {
|
||||
if (this.roomId == null) {
|
||||
return "";
|
||||
}
|
||||
return this.roomId.toString();
|
||||
}
|
||||
|
||||
public long getRoomIdAsLong() {
|
||||
String roomIdAsString = this.getRoomIdAsString();
|
||||
if (roomIdAsString.trim().isEmpty()) {
|
||||
return 0L;
|
||||
}
|
||||
return Long.parseLong(roomIdAsString);
|
||||
}
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* 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.servers.netty.handler.base;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
|
||||
import io.netty.handler.ssl.SslCloseCompletionEvent;
|
||||
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
|
||||
import io.netty.util.concurrent.ScheduledFuture;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* 连接处理器
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BaseConnectionHandler<ConnectionHandler extends BaseConnectionHandler<?>> extends SimpleChannelInboundHandler<FullHttpResponse> {
|
||||
|
||||
private final WebSocketClientHandshaker handshaker;
|
||||
@Getter
|
||||
private ChannelPromise handshakeFuture;
|
||||
private final IBaseConnectionListener<ConnectionHandler> listener;
|
||||
/**
|
||||
* 客户端发送心跳包
|
||||
*/
|
||||
private ScheduledFuture<?> scheduledFuture = null;
|
||||
|
||||
public BaseConnectionHandler(WebSocketClientHandshaker handshaker, IBaseConnectionListener<ConnectionHandler> listener) {
|
||||
this.handshaker = handshaker;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public BaseConnectionHandler(WebSocketClientHandshaker handshaker) {
|
||||
this(handshaker, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
this.handshakeFuture = ctx.newPromise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) {
|
||||
this.handshaker.handshake(ctx.channel());
|
||||
}
|
||||
|
||||
protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse msg) throws Exception {
|
||||
// 判断是否正确握手
|
||||
if (this.handshaker.isHandshakeComplete()) {
|
||||
handshakeSuccessfully(ctx, msg);
|
||||
} else {
|
||||
try {
|
||||
handshakeSuccessfully(ctx, msg);
|
||||
} catch (WebSocketHandshakeException e) {
|
||||
handshakeFailed(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("userEventTriggered {}", evt.getClass());
|
||||
}
|
||||
if (evt instanceof SslHandshakeCompletionEvent) {
|
||||
heartbeatCancel();
|
||||
heartbeatStart(ctx);
|
||||
if (this.listener != null) {
|
||||
listener.onConnected((ConnectionHandler) BaseConnectionHandler.this);
|
||||
}
|
||||
} else if (evt instanceof SslCloseCompletionEvent) {
|
||||
heartbeatCancel();
|
||||
if (this.listener != null) {
|
||||
listener.onDisconnected((ConnectionHandler) BaseConnectionHandler.this);
|
||||
}
|
||||
} else {
|
||||
log.error("待处理 {}", evt.getClass());
|
||||
}
|
||||
super.userEventTriggered(ctx, evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始发送心跳包
|
||||
*/
|
||||
private void heartbeatStart(ChannelHandlerContext ctx) {
|
||||
scheduledFuture = ctx.executor().scheduleAtFixedRate(() -> {
|
||||
sendHeartbeat(ctx);
|
||||
}, getHeartbeatInitialDelay(), getHeartbeatPeriod(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消发送心跳包
|
||||
*/
|
||||
private void heartbeatCancel() {
|
||||
if (null != scheduledFuture && !scheduledFuture.isCancelled()) {
|
||||
scheduledFuture.cancel(true);
|
||||
scheduledFuture = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void sendHeartbeat(ChannelHandlerContext ctx);
|
||||
|
||||
public abstract void sendAuthRequest(Channel channel);
|
||||
|
||||
protected abstract long getHeartbeatPeriod();
|
||||
|
||||
protected abstract long getHeartbeatInitialDelay();
|
||||
|
||||
private void handshakeSuccessfully(ChannelHandlerContext ctx, FullHttpResponse msg) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("握手完成!");
|
||||
}
|
||||
this.handshaker.finishHandshake(ctx.channel(), msg);
|
||||
this.handshakeFuture.setSuccess();
|
||||
}
|
||||
|
||||
private void handshakeFailed(FullHttpResponse msg, WebSocketHandshakeException e) {
|
||||
log.error("握手失败!status:" + msg.status(), e);
|
||||
this.handshakeFuture.setFailure(e);
|
||||
if (listener != null) {
|
||||
this.listener.onConnectFailed((ConnectionHandler) this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
log.error("exceptionCaught", cause);
|
||||
if (!this.handshakeFuture.isDone()) {
|
||||
this.handshakeFuture.setFailure(cause);
|
||||
}
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<!--
|
||||
~ 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>ruoyi-live</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<artifactId>live-chat-client-servers</artifactId>
|
||||
<name>live-chat-client-servers</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>live-chat-client-servers-netty</module>
|
||||
<module>live-chat-client-servers-netty-client</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -1,71 +0,0 @@
|
||||
<!--
|
||||
~ 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>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>live-chat-client-bilibili</artifactId>
|
||||
<name>live-chat-client-bilibili</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>com.aayushatharva.brotli4j</groupId>
|
||||
<artifactId>brotli4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</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>
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.api;
|
||||
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.api.request.BilibiliLikeReportV3Request;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.api.request.BilibiliSendMsgRequest;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLiveChatCookieUtil;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static tech.ordinaryroad.live.chat.client.commons.base.msg.BaseMsg.OBJECT_MAPPER;
|
||||
|
||||
/**
|
||||
* B站API简易版
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/5/5
|
||||
*/
|
||||
@Slf4j
|
||||
public class BilibiliApis {
|
||||
|
||||
public static final TimedCache<Long, String> GIFT_IMG_CACHE = new TimedCache<>(TimeUnit.DAYS.toMillis(1));
|
||||
public static final String KEY_COOKIE_CSRF = "bili_jct";
|
||||
public static final String KEY_UID = "DedeUserID";
|
||||
|
||||
@SneakyThrows
|
||||
public static RoomInitResult roomInit(long roomId, String cookie) {
|
||||
@Cleanup
|
||||
HttpResponse response = createGetRequest("https://api.live.bilibili.com/room/v1/Room/room_init?id=" + roomId, cookie).execute();
|
||||
JsonNode dataJsonNode = responseInterceptor(response.body());
|
||||
return OBJECT_MAPPER.readValue(dataJsonNode.toString(), RoomInitResult.class);
|
||||
}
|
||||
|
||||
public static JsonNode roomGiftConfig(long roomId, String cookie) {
|
||||
@Cleanup
|
||||
HttpResponse response = createGetRequest("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/roomGiftConfig?platform=pc&source=live&build=0&global_version=0&room_id=" + roomId, cookie).execute();
|
||||
return responseInterceptor(response.body());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param roomId
|
||||
* @param type 直播间用0
|
||||
* @return <pre>{@code
|
||||
* {
|
||||
* "group": "live",
|
||||
* "business_id": 0,
|
||||
* "refresh_row_factor": 0.125,
|
||||
* "refresh_rate": 100,
|
||||
* "max_delay": 5000,
|
||||
* "token": "-wm5-Qo4BBAztd1qp5ZJpgyTMRBhCc7yikz5d9rAd63PV46G9BMwl0R10kMM8Ilb-UieZGjLtipPrz4Cvi0DdhGFwOi8PJpFN9K-LoXh6Z_4yjEIwgRerDiMIstHzJ80J3B7wnRisAYkWA==",
|
||||
* "host_list": [{
|
||||
* "host": "ali-bj-live-comet-09.chat.bilibili.com",
|
||||
* "port": 2243,
|
||||
* "wss_port": 443,
|
||||
* "ws_port": 2244
|
||||
* }, {
|
||||
* "host": "ali-gz-live-comet-02.chat.bilibili.com",
|
||||
* "port": 2243,
|
||||
* "wss_port": 443,
|
||||
* "ws_port": 2244
|
||||
* }, {
|
||||
* "host": "broadcastlv.chat.bilibili.com",
|
||||
* "port": 2243,
|
||||
* "wss_port": 443,
|
||||
* "ws_port": 2244
|
||||
* }]
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
public static JsonNode getDanmuInfo(long roomId, int type, String cookie) {
|
||||
@Cleanup
|
||||
HttpResponse response = createGetRequest("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=" + roomId + "&type=" + type, cookie).execute();
|
||||
return responseInterceptor(response.body());
|
||||
}
|
||||
|
||||
public static String getGiftImgById(long giftId, long roomId) {
|
||||
if (!GIFT_IMG_CACHE.containsKey(giftId)) {
|
||||
ThreadUtil.execAsync(() -> {
|
||||
updateGiftImgCache(roomId, null);
|
||||
});
|
||||
}
|
||||
|
||||
return GIFT_IMG_CACHE.get(giftId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新礼物图片缓存
|
||||
*/
|
||||
public static void updateGiftImgCache(long roomId, String cookie) {
|
||||
JsonNode jsonNode = roomGiftConfig(roomId, cookie);
|
||||
for (JsonNode node : jsonNode.get("global_gift").get("list")) {
|
||||
long giftId = node.get("id").asLong();
|
||||
String giftImgUrl = node.get("webp").asText();
|
||||
GIFT_IMG_CACHE.put(giftId, giftImgUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param request {@link BilibiliSendMsgRequest}
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void sendMsg(BilibiliSendMsgRequest request, String cookie) {
|
||||
if (StrUtil.isBlank(cookie)) {
|
||||
throw new BaseException("发送弹幕接口cookie不能为空");
|
||||
}
|
||||
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(request);
|
||||
@Cleanup HttpResponse execute = HttpUtil.createPost("https://api.live.bilibili.com/msg/send")
|
||||
.cookie(cookie)
|
||||
.form(stringObjectMap)
|
||||
.execute();
|
||||
responseInterceptor(execute.body());
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送弹幕
|
||||
*
|
||||
* @param msg 内容
|
||||
* @param realRoomId 真实房间id
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void sendMsg(String msg, long realRoomId, String cookie) {
|
||||
String biliJct = OrLiveChatCookieUtil.getCookieByName(cookie, KEY_COOKIE_CSRF, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + KEY_COOKIE_CSRF);
|
||||
});
|
||||
BilibiliSendMsgRequest request = new BilibiliSendMsgRequest(msg, StrUtil.toString(ZonedDateTime.now(ZoneId.of("Asia/Shanghai")).toEpochSecond()), realRoomId, biliJct, biliJct);
|
||||
sendMsg(request, cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为主播点赞
|
||||
*
|
||||
* @param request {@link BilibiliLikeReportV3Request}
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void likeReportV3(BilibiliLikeReportV3Request request, String cookie) {
|
||||
if (StrUtil.isBlank(cookie)) {
|
||||
throw new BaseException("为主播点赞接口cookie不能为空");
|
||||
}
|
||||
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(request);
|
||||
@Cleanup HttpResponse execute = HttpUtil.createPost("https://api.live.bilibili.com/xlive/app-ucenter/v1/like_info_v3/like/likeReportV3")
|
||||
.cookie(cookie)
|
||||
.form(stringObjectMap)
|
||||
.execute();
|
||||
responseInterceptor(execute.body());
|
||||
}
|
||||
|
||||
/**
|
||||
* 为主播点赞
|
||||
*
|
||||
* @param anchor_id 主播Uid {@link RoomInitResult#uid}
|
||||
* @param realRoomId 真实房间Id {@link RoomInitResult#room_id}
|
||||
* @param cookie Cookie
|
||||
*/
|
||||
public static void likeReportV3(long anchor_id, long realRoomId, String cookie) {
|
||||
String uid = OrLiveChatCookieUtil.getCookieByName(cookie, KEY_UID, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + KEY_UID);
|
||||
});
|
||||
String biliJct = OrLiveChatCookieUtil.getCookieByName(cookie, KEY_COOKIE_CSRF, () -> {
|
||||
throw new BaseException("cookie中缺少参数" + KEY_COOKIE_CSRF);
|
||||
});
|
||||
BilibiliLikeReportV3Request request = new BilibiliLikeReportV3Request(realRoomId, uid, anchor_id, biliJct, biliJct);
|
||||
likeReportV3(request, cookie);
|
||||
}
|
||||
|
||||
public static HttpRequest createGetRequest(String url, String cookies) {
|
||||
return HttpUtil.createGet(url)
|
||||
.cookie(cookies);
|
||||
}
|
||||
|
||||
private static JsonNode responseInterceptor(String responseString) {
|
||||
try {
|
||||
JsonNode jsonNode = OBJECT_MAPPER.readTree(responseString);
|
||||
int code = jsonNode.get("code").asInt();
|
||||
if (code == 0) {
|
||||
// 成功
|
||||
return jsonNode.get("data");
|
||||
} else {
|
||||
throw new BaseException(jsonNode.get("message").asText());
|
||||
}
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new BaseException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class RoomInitResult {
|
||||
private long room_id;
|
||||
private int short_id;
|
||||
private long uid;
|
||||
private int need_p2p;
|
||||
private boolean is_hidden;
|
||||
private boolean is_locked;
|
||||
private boolean is_portrait;
|
||||
private int live_status;
|
||||
private int hidden_till;
|
||||
private int lock_till;
|
||||
private boolean encrypted;
|
||||
private boolean pwd_verified;
|
||||
private long live_time;
|
||||
private int room_shield;
|
||||
private int is_sp;
|
||||
private int special_type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.api.request;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2024/1/31
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class BilibiliLikeReportV3Request {
|
||||
/**
|
||||
* 本次点赞次数
|
||||
*/
|
||||
private int click_time = 1;
|
||||
/**
|
||||
* 房间真实ID
|
||||
*/
|
||||
private long room_id;
|
||||
/**
|
||||
* Cookie中的DedeUserID
|
||||
*/
|
||||
private String uid;
|
||||
/**
|
||||
* RoomInitResult中的uid
|
||||
*/
|
||||
private long anchor_id;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf_token;
|
||||
/**
|
||||
* 暂时留空
|
||||
*/
|
||||
private String visit_id = StrUtil.EMPTY;
|
||||
|
||||
public BilibiliLikeReportV3Request(long room_id, String uid, long anchor_id, String csrf, String csrf_token) {
|
||||
this.room_id = room_id;
|
||||
this.uid = uid;
|
||||
this.anchor_id = anchor_id;
|
||||
this.csrf = csrf;
|
||||
this.csrf_token = csrf_token;
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.api.request;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/7
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class BilibiliSendMsgRequest {
|
||||
private String bubble = "0";
|
||||
/**
|
||||
* 弹幕内容
|
||||
*/
|
||||
private String msg;
|
||||
/**
|
||||
* 弹幕颜色
|
||||
*/
|
||||
private String color = "16777215";
|
||||
private String mode = "1";
|
||||
private String room_type = "0";
|
||||
private String jumpfrom = "0";
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
private String fontsize = "25";
|
||||
/**
|
||||
* 时间戳(秒)
|
||||
*/
|
||||
private String rnd;
|
||||
/**
|
||||
* 房间真实ID
|
||||
*/
|
||||
private long roomid;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf;
|
||||
/**
|
||||
* Cookie中的bili_jct
|
||||
*/
|
||||
private String csrf_token;
|
||||
|
||||
public BilibiliSendMsgRequest(String msg, String rnd, long roomid, String csrf, String csrf_token) {
|
||||
this.msg = msg;
|
||||
this.rnd = rnd;
|
||||
this.roomid = roomid;
|
||||
this.csrf = csrf;
|
||||
this.csrf_token = csrf_token;
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.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.bilibili.api.BilibiliApis;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.config.BilibiliLiveChatClientConfig;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.BilibiliCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.listener.IBilibiliConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.listener.IBilibiliMsgListener;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.msg.base.IBilibiliMsg;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.netty.handler.BilibiliBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.netty.handler.BilibiliConnectionHandler;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.exception.BaseException;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.base.BaseNettyClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* B站直播间弹幕客户端
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/20
|
||||
*/
|
||||
@Slf4j
|
||||
public class BilibiliLiveChatClient extends BaseNettyClient<
|
||||
BilibiliLiveChatClientConfig,
|
||||
BilibiliCmdEnum,
|
||||
IBilibiliMsg,
|
||||
IBilibiliMsgListener,
|
||||
BilibiliConnectionHandler,
|
||||
BilibiliBinaryFrameHandler
|
||||
> {
|
||||
|
||||
private BilibiliApis.RoomInitResult roomInitResult = new BilibiliApis.RoomInitResult();
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, List<IBilibiliMsgListener> msgListeners, IBilibiliConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, workerGroup, connectionListener);
|
||||
addMsgListeners(msgListeners);
|
||||
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, IBilibiliMsgListener msgListener, IBilibiliConnectionListener connectionListener, EventLoopGroup workerGroup) {
|
||||
super(config, workerGroup, connectionListener);
|
||||
addMsgListener(msgListener);
|
||||
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, IBilibiliMsgListener msgListener, IBilibiliConnectionListener connectionListener) {
|
||||
this(config, msgListener, connectionListener, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config, IBilibiliMsgListener msgListener) {
|
||||
this(config, msgListener, null, new NioEventLoopGroup());
|
||||
}
|
||||
|
||||
public BilibiliLiveChatClient(BilibiliLiveChatClientConfig config) {
|
||||
this(config, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
roomInitResult = BilibiliApis.roomInit(getConfig().getRoomId(), getConfig().getCookie());
|
||||
super.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BilibiliConnectionHandler initConnectionHandler(IBaseConnectionListener<BilibiliConnectionHandler> clientConnectionListener) {
|
||||
return new BilibiliConnectionHandler(
|
||||
WebSocketClientHandshakerFactory.newHandshaker(getWebsocketUri(), WebSocketVersion.V13, null, true, new DefaultHttpHeaders(), getConfig().getMaxFramePayloadLength()),
|
||||
BilibiliLiveChatClient.this, clientConnectionListener
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BilibiliBinaryFrameHandler initBinaryFrameHandler() {
|
||||
return new BilibiliBinaryFrameHandler(super.msgListeners, BilibiliLiveChatClient.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDanmu(Object danmu, Runnable success, Consumer<Throwable> failed) {
|
||||
if (!checkCanSendDanmu(false)) {
|
||||
return;
|
||||
}
|
||||
if (danmu instanceof String) {
|
||||
String msg = (String) danmu;
|
||||
try {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} bilibili发送弹幕 {}", getConfig().getRoomId(), danmu);
|
||||
}
|
||||
|
||||
boolean sendSuccess = false;
|
||||
try {
|
||||
BilibiliApis.sendMsg(msg, roomInitResult.getRoom_id(), getConfig().getCookie());
|
||||
sendSuccess = true;
|
||||
} catch (Exception e) {
|
||||
log.error("bilibili弹幕发送失败", e);
|
||||
if (failed != null) {
|
||||
failed.accept(e);
|
||||
}
|
||||
}
|
||||
if (!sendSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("bilibili弹幕发送成功 {}", danmu);
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
finishSendDanmu();
|
||||
} catch (Exception e) {
|
||||
log.error("bilibili弹幕发送失败", e);
|
||||
if (failed != null) {
|
||||
failed.accept(e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
super.sendDanmu(danmu, success, failed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickLike(int count, Runnable success, Consumer<Throwable> failed) {
|
||||
if (count <= 0) {
|
||||
throw new BaseException("点赞次数必须大于0");
|
||||
}
|
||||
|
||||
boolean successfullyClicked = false;
|
||||
try {
|
||||
BilibiliApis.likeReportV3(roomInitResult.getUid(), roomInitResult.getRoom_id(), getConfig().getCookie());
|
||||
successfullyClicked = true;
|
||||
} catch (Exception e) {
|
||||
log.error("Bilibili为直播间点赞失败", e);
|
||||
if (failed != null) {
|
||||
failed.accept(e);
|
||||
}
|
||||
}
|
||||
if (!successfullyClicked) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Bilibili为直播间点赞成功");
|
||||
}
|
||||
if (success != null) {
|
||||
success.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.ProtoverEnum;
|
||||
import tech.ordinaryroad.live.chat.client.commons.util.OrLiveChatNumberUtil;
|
||||
import tech.ordinaryroad.live.chat.client.servers.netty.client.config.BaseNettyClientConfig;
|
||||
|
||||
/**
|
||||
* B站直播间弹幕客户端配置
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuperBuilder(toBuilder = true)
|
||||
public class BilibiliLiveChatClientConfig extends BaseNettyClientConfig {
|
||||
|
||||
/**
|
||||
* @see ProtoverEnum
|
||||
*/
|
||||
@Builder.Default
|
||||
private ProtoverEnum protover = ProtoverEnum.NORMAL_ZLIB;
|
||||
|
||||
@Builder.Default
|
||||
private String websocketUri = "wss://broadcastlv.chat.bilibili.com:443/sub";
|
||||
|
||||
@Override
|
||||
public Long getRoomId() {
|
||||
return OrLiveChatNumberUtil.parseLong(super.getRoomId());
|
||||
}
|
||||
|
||||
public void setProtover(ProtoverEnum protover) {
|
||||
ProtoverEnum oldValue = this.protover;
|
||||
this.protover = protover;
|
||||
super.propertyChangeSupport.firePropertyChange("protover", oldValue, protover);
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.constant;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum BilibiliCmdEnum {
|
||||
/**
|
||||
* 游客状态下,5分钟后会出现登录提示,弹幕中的用户名、用户id等信息将不再可见
|
||||
*/
|
||||
LOG_IN_NOTICE,
|
||||
/**
|
||||
* 收到弹幕
|
||||
*/
|
||||
DANMU_MSG,
|
||||
/**
|
||||
* 收到礼物
|
||||
*/
|
||||
SEND_GIFT,
|
||||
/**
|
||||
* 有人上舰
|
||||
*/
|
||||
GUARD_BUY,
|
||||
/**
|
||||
* 欢迎舰长
|
||||
*/
|
||||
WELCOME_GUARD,
|
||||
WELCOME,
|
||||
/**
|
||||
* 礼物连击
|
||||
*/
|
||||
COMBO_SEND,
|
||||
/**
|
||||
* 欢迎高能用户、(舰长?待验证)特殊消息
|
||||
*/
|
||||
ENTRY_EFFECT,
|
||||
HOT_RANK_CHANGED,
|
||||
HOT_RANK_CHANGED_V2,
|
||||
INTERACT_WORD,
|
||||
/**
|
||||
* 开始直播
|
||||
*/
|
||||
LIVE,
|
||||
LIVE_INTERACTIVE_GAME,
|
||||
NOTICE_MSG,
|
||||
/**
|
||||
* 高能榜数量更新
|
||||
*/
|
||||
ONLINE_RANK_COUNT,
|
||||
ONLINE_RANK_TOP3,
|
||||
ONLINE_RANK_V2,
|
||||
PK_BATTLE_END,
|
||||
PK_BATTLE_FINAL_PROCESS,
|
||||
PK_BATTLE_PROCESS,
|
||||
PK_BATTLE_PROCESS_NEW,
|
||||
PK_BATTLE_SETTLE,
|
||||
PK_BATTLE_SETTLE_USER,
|
||||
PK_BATTLE_SETTLE_V2,
|
||||
/**
|
||||
* 主播准备中
|
||||
*/
|
||||
PREPARING,
|
||||
ROOM_REAL_TIME_MESSAGE_UPDATE,
|
||||
/**
|
||||
* 停止直播的房间ID列表
|
||||
*/
|
||||
STOP_LIVE_ROOM_LIST,
|
||||
/**
|
||||
* 醒目留言
|
||||
*/
|
||||
SUPER_CHAT_MESSAGE,
|
||||
SUPER_CHAT_MESSAGE_JPN,
|
||||
/**
|
||||
* 删除醒目留言
|
||||
*/
|
||||
SUPER_CHAT_MESSAGE_DELETE,
|
||||
WIDGET_BANNER,
|
||||
/**
|
||||
* 点赞数更新
|
||||
*/
|
||||
LIKE_INFO_V3_UPDATE,
|
||||
/**
|
||||
* 为主播点赞
|
||||
*/
|
||||
LIKE_INFO_V3_CLICK,
|
||||
HOT_ROOM_NOTIFY,
|
||||
/**
|
||||
* 观看人数变化
|
||||
*/
|
||||
WATCHED_CHANGE,
|
||||
POPULAR_RANK_CHANGED,
|
||||
COMMON_NOTICE_DANMAKU,
|
||||
LIVE_MULTI_VIEW_CHANGE,
|
||||
RECOMMEND_CARD,
|
||||
PK_BATTLE_START_NEW,
|
||||
PK_BATTLE_ENTRANCE,
|
||||
AREA_RANK_CHANGED,
|
||||
ROOM_BLOCK_MSG,
|
||||
USER_TOAST_MSG,
|
||||
PK_BATTLE_PRE_NEW,
|
||||
PK_BATTLE_RANK_CHANGE,
|
||||
PK_BATTLE_START,
|
||||
PK_BATTLE_PRE,
|
||||
PLAY_TAG,
|
||||
;
|
||||
|
||||
public static BilibiliCmdEnum getByString(String cmd) {
|
||||
try {
|
||||
return BilibiliCmdEnum.valueOf(cmd);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.constant;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum OperationEnum {
|
||||
HANDSHAKE(0),
|
||||
HANDSHAKE_REPLY(1),
|
||||
/**
|
||||
* 心跳包
|
||||
*/
|
||||
HEARTBEAT(2),
|
||||
/**
|
||||
* 心跳包回复(人气值)
|
||||
*/
|
||||
HEARTBEAT_REPLY(3),
|
||||
SEND_MSG(4),
|
||||
|
||||
/**
|
||||
* 普通包(命令)
|
||||
*/
|
||||
SEND_SMS_REPLY(5),
|
||||
DISCONNECT_REPLY(6),
|
||||
|
||||
/**
|
||||
* 认证包
|
||||
*/
|
||||
AUTH(7),
|
||||
|
||||
/**
|
||||
* 认证包回复
|
||||
*/
|
||||
AUTH_REPLY(8),
|
||||
RAW(9),
|
||||
PROTO_READY(10),
|
||||
PROTO_FINISH(11),
|
||||
CHANGE_ROOM(12),
|
||||
CHANGE_ROOM_REPLY(13),
|
||||
REGISTER(14),
|
||||
REGISTER_REPLY(15),
|
||||
UNREGISTER(16),
|
||||
UNREGISTER_REPLY(17),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
|
||||
public static OperationEnum getByCode(int code) {
|
||||
for (OperationEnum value : OperationEnum.values()) {
|
||||
if (value.code == code) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.constant;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/5
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ProtoverEnum {
|
||||
/**
|
||||
* 普通包正文不使用压缩
|
||||
*/
|
||||
NORMAL_NO_COMPRESSION(0),
|
||||
/**
|
||||
* 心跳及认证包正文不使用压缩
|
||||
*/
|
||||
HEARTBEAT_AUTH_NO_COMPRESSION(1),
|
||||
/**
|
||||
* 普通包正文使用zlib压缩
|
||||
*/
|
||||
NORMAL_ZLIB(2),
|
||||
/**
|
||||
* 普通包正文使用brotli压缩,解压为一个带头部的协议0普通包
|
||||
*/
|
||||
NORMAL_BROTLI(3),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
|
||||
|
||||
public static ProtoverEnum getByCode(int code) {
|
||||
for (ProtoverEnum value : ProtoverEnum.values()) {
|
||||
if (value.code == code) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.listener;
|
||||
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.netty.handler.BilibiliConnectionHandler;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.IBaseConnectionListener;
|
||||
|
||||
/**
|
||||
* 连接回调
|
||||
*
|
||||
* @author mjz
|
||||
* @date 2023/8/21
|
||||
*/
|
||||
public interface IBilibiliConnectionListener extends IBaseConnectionListener<BilibiliConnectionHandler> {
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.listener;
|
||||
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.BilibiliCmdEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.msg.*;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.netty.handler.BilibiliBinaryFrameHandler;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.listener.*;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/7
|
||||
*/
|
||||
public interface IBilibiliMsgListener extends IBaseMsgListener<BilibiliBinaryFrameHandler, BilibiliCmdEnum>,
|
||||
IDanmuMsgListener<BilibiliBinaryFrameHandler, DanmuMsgMsg>,
|
||||
IGiftMsgListener<BilibiliBinaryFrameHandler, SendGiftMsg>,
|
||||
ISuperChatMsgListener<BilibiliBinaryFrameHandler, SuperChatMessageMsg>,
|
||||
IEnterRoomMsgListener<BilibiliBinaryFrameHandler, InteractWordMsg>,
|
||||
ILikeMsgListener<BilibiliBinaryFrameHandler, LikeInfoV3ClickMsg> {
|
||||
|
||||
/**
|
||||
* 收到礼物
|
||||
*
|
||||
* @param binaryFrameHandler BilibiliBinaryFrameHandler
|
||||
* @param msg SendSmsReplyMsg
|
||||
* @deprecated use {@link IGiftMsgListener#onGiftMsg(Object, Object)}
|
||||
*/
|
||||
default void onSendGift(BilibiliBinaryFrameHandler binaryFrameHandler, SendSmsReplyMsg msg) {
|
||||
this.onSendGift(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link IGiftMsgListener#onGiftMsg(Object)}
|
||||
*/
|
||||
default void onSendGift(SendSmsReplyMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通用户进入直播间
|
||||
*
|
||||
* @param binaryFrameHandler BilibiliBinaryFrameHandler
|
||||
* @param msg SendSmsReplyMsg
|
||||
* @deprecated use {@link IEnterRoomMsgListener#onEnterRoomMsg}
|
||||
*/
|
||||
default void onEnterRoom(BilibiliBinaryFrameHandler binaryFrameHandler, SendSmsReplyMsg msg) {
|
||||
this.onEnterRoom(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link IEnterRoomMsgListener#onEnterRoomMsg}
|
||||
*/
|
||||
default void onEnterRoom(SendSmsReplyMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 入场效果(高能用户)
|
||||
*
|
||||
* @param binaryFrameHandler BilibiliBinaryFrameHandler
|
||||
* @param sendSmsReplyMsg SendSmsReplyMsg
|
||||
*/
|
||||
default void onEntryEffect(BilibiliBinaryFrameHandler binaryFrameHandler, SendSmsReplyMsg sendSmsReplyMsg) {
|
||||
this.onEntryEffect(sendSmsReplyMsg);
|
||||
}
|
||||
|
||||
default void onEntryEffect(SendSmsReplyMsg sendSmsReplyMsg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 观看人数变化
|
||||
*
|
||||
* @param binaryFrameHandler BilibiliBinaryFrameHandler
|
||||
* @param msg SendSmsReplyMsg
|
||||
*/
|
||||
default void onWatchedChange(BilibiliBinaryFrameHandler binaryFrameHandler, SendSmsReplyMsg msg) {
|
||||
this.onWatchedChange(msg);
|
||||
}
|
||||
|
||||
default void onWatchedChange(SendSmsReplyMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 为主播点赞
|
||||
*
|
||||
* @param binaryFrameHandler BilibiliBinaryFrameHandler
|
||||
* @param msg SendSmsReplyMsg
|
||||
* @deprecated use {@link ILikeMsgListener#onLikeMsg}
|
||||
*/
|
||||
default void onClickLike(BilibiliBinaryFrameHandler binaryFrameHandler, SendSmsReplyMsg msg) {
|
||||
this.onClickLike(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ILikeMsgListener#onLikeMsg}
|
||||
*/
|
||||
default void onClickLike(SendSmsReplyMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞数更新
|
||||
*
|
||||
* @param binaryFrameHandler BilibiliBinaryFrameHandler
|
||||
* @param msg SendSmsReplyMsg
|
||||
*/
|
||||
default void onClickUpdate(BilibiliBinaryFrameHandler binaryFrameHandler, SendSmsReplyMsg msg) {
|
||||
this.onClickUpdate(msg);
|
||||
}
|
||||
|
||||
default void onClickUpdate(SendSmsReplyMsg msg) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.msg;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.OperationEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.ProtoverEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.msg.base.BaseBilibiliMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@RequiredArgsConstructor
|
||||
public class AuthMsg extends BaseBilibiliMsg {
|
||||
|
||||
/**
|
||||
* 用户uid,0代表游客
|
||||
*/
|
||||
private long uid;
|
||||
|
||||
/**
|
||||
* 房间id room_id,不是短id short_id
|
||||
* 可以通过将url参数id改为直播地址中的数字来查询房间真实id
|
||||
* example: <a href="https://api.live.bilibili.com/room/v1/Room/room_init?id=6">https://api.live.bilibili.com/room/v1/Room/room_init?id=6</a>
|
||||
*/
|
||||
private final long roomid;
|
||||
|
||||
/**
|
||||
* 协议版本
|
||||
*
|
||||
* @see ProtoverEnum#getCode()
|
||||
*/
|
||||
private final int protover;
|
||||
|
||||
/**
|
||||
* 平台标识
|
||||
*/
|
||||
private String platform = "web";
|
||||
private int type = 2;
|
||||
|
||||
/**
|
||||
* 必须字段
|
||||
*
|
||||
* @since 2023-08-19
|
||||
*/
|
||||
private final String buvid;
|
||||
|
||||
/**
|
||||
* 认证秘钥(必须字段)
|
||||
*
|
||||
* @since @since 2023-08-19
|
||||
*/
|
||||
private final String key;
|
||||
|
||||
@Override
|
||||
public ProtoverEnum getProtoverEnum() {
|
||||
return ProtoverEnum.getByCode(this.protover);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperationEnum getOperationEnum() {
|
||||
return OperationEnum.AUTH;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.msg;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.OperationEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.ProtoverEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.msg.base.BaseBilibiliMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/1/6
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AuthReplyMsg extends BaseBilibiliMsg {
|
||||
|
||||
/**
|
||||
* 0: OK,-101: TOKEN_ERROR
|
||||
*/
|
||||
private int code;
|
||||
|
||||
@JsonIgnore
|
||||
private int protover;
|
||||
|
||||
@Override
|
||||
public ProtoverEnum getProtoverEnum() {
|
||||
return ProtoverEnum.getByCode(protover);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperationEnum getOperationEnum() {
|
||||
return OperationEnum.AUTH_REPLY;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* 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.bilibili.msg;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.constant.OperationEnum;
|
||||
import tech.ordinaryroad.live.chat.client.bilibili.msg.base.BaseBilibiliMsg;
|
||||
import tech.ordinaryroad.live.chat.client.commons.base.msg.IDanmuMsg;
|
||||
|
||||
/**
|
||||
* @author mjz
|
||||
* @date 2023/9/8
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DanmuMsgMsg extends BaseBilibiliMsg implements IDanmuMsg {
|
||||
|
||||
private JsonNode info;
|
||||
private String dm_v2;
|
||||
|
||||
@Override
|
||||
public OperationEnum getOperationEnum() {
|
||||
return OperationEnum.SEND_SMS_REPLY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBadgeName() {
|
||||
JsonNode jsonNode3 = info.get(3);
|
||||
if (jsonNode3.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return jsonNode3.get(1).asText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getBadgeLevel() {
|
||||
JsonNode jsonNode3 = info.get(3);
|
||||
if (jsonNode3.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return (byte) jsonNode3.get(0).asInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUid() {
|
||||
JsonNode jsonNode2 = info.get(2);
|
||||
return jsonNode2.get(0).asText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
JsonNode jsonNode2 = info.get(2);
|
||||
return jsonNode2.get(1).asText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserAvatar() {
|
||||
String avatar = null;
|
||||
try {
|
||||
tech.ordinaryroad.live.chat.client.bilibili.protobuf.dm_v2 dmV2 = tech.ordinaryroad.live.chat.client.bilibili.protobuf.dm_v2.parseFrom(Base64.decode(dm_v2));
|
||||
avatar = dmV2.getDmV220().getAvatar();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return avatar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContent() {
|
||||
JsonNode jsonNode1 = info.get(1);
|
||||
return jsonNode1.asText();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user