Compare commits
3 Commits
master
...
9521e9d5c8
| Author | SHA1 | Date | |
|---|---|---|---|
| 9521e9d5c8 | |||
| 54ac47c8b4 | |||
| b178010f8f |
32
biliapi/pom.xml
Normal file
32
biliapi/pom.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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.yutou</groupId>
|
||||||
|
<artifactId>bilibili</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>biliapi</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.reactivex.rxjava3</groupId>
|
||||||
|
<artifactId>rxjava</artifactId>
|
||||||
|
<version>3.1.8</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aayushatharva.brotli4j</groupId>
|
||||||
|
<artifactId>brotli4j</artifactId>
|
||||||
|
<version>1.16.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
192
biliapi/src/main/java/com/yutou/Main.java
Normal file
192
biliapi/src/main/java/com/yutou/Main.java
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
package com.yutou;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.bili.api.LiveApi;
|
||||||
|
import com.yutou.bili.api.UserApi;
|
||||||
|
import com.yutou.bili.bean.live.LiveRoomConfig;
|
||||||
|
import com.yutou.bili.bean.live.LiveRoomPlayInfo;
|
||||||
|
import com.yutou.bili.bean.live.SpiBean;
|
||||||
|
import com.yutou.bili.bean.login.LoginCookie;
|
||||||
|
import com.yutou.bili.bean.login.UserInfoBean;
|
||||||
|
import com.yutou.bili.enums.LiveProtocol;
|
||||||
|
import com.yutou.bili.enums.LiveVideoCodec;
|
||||||
|
import com.yutou.bili.enums.LiveVideoDefinition;
|
||||||
|
import com.yutou.bili.enums.LiveVideoFormat;
|
||||||
|
import com.yutou.bili.net.BiliLiveNetApiManager;
|
||||||
|
import com.yutou.bili.net.BiliLoginNetApiManager;
|
||||||
|
import com.yutou.bili.databases.BiliBiliLoginDatabase;
|
||||||
|
import com.yutou.bili.net.BiliUserNetApiManager;
|
||||||
|
import com.yutou.bili.net.WebSocketManager;
|
||||||
|
import com.yutou.inter.IHttpApiCheckCallback;
|
||||||
|
import com.yutou.okhttp.HttpCallback;
|
||||||
|
import com.yutou.okhttp.HttpLoggingInterceptor;
|
||||||
|
import com.yutou.utils.Log;
|
||||||
|
import jakarta.xml.bind.DatatypeConverter;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
HttpLoggingInterceptor.setLog(false);
|
||||||
|
HttpLoggingInterceptor.setLog(true);
|
||||||
|
// getPlayUrl();
|
||||||
|
LiveRoomConfig config=new LiveRoomConfig();
|
||||||
|
LoginCookie cookie = BiliBiliLoginDatabase.getInstance().get();
|
||||||
|
config.setLogin(true);
|
||||||
|
config.setUid(cookie.getDedeUserID());
|
||||||
|
config.setRoomId(String.valueOf(855204));
|
||||||
|
config.setRoomId(String.valueOf(22642754));
|
||||||
|
config.setRoomId(String.valueOf(81004));
|
||||||
|
WebSocketManager.getInstance().addRoom(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void testSocket(SpiBean spi) {
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
// json.put("roomid", "32805602");
|
||||||
|
json.put("roomid", "855204");
|
||||||
|
json.put("protover", "3");
|
||||||
|
json.put("platform", "web");
|
||||||
|
json.put("type", 2);
|
||||||
|
json.put("buvid",spi.getB_3());
|
||||||
|
json.put("key", "aaaabbb");
|
||||||
|
Log.i(json);
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
// outputStream.write(toLH(json.toString().length() + 16));
|
||||||
|
outputStream.write(new byte[]{0, 0, 1, 68, 0, 16, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1});
|
||||||
|
outputStream.write(json.toJSONString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
outputStream.flush();
|
||||||
|
System.out.println("\n\n\n");
|
||||||
|
String str = DatatypeConverter.printHexBinary(outputStream.toByteArray());
|
||||||
|
for (int i = 0; i < str.length(); i = i + 4) {
|
||||||
|
if (i % 32 == 0 && i != 0) {
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
if (str.length() - i > 4) {
|
||||||
|
System.out.print(str.substring(i, i + 4) + " ");
|
||||||
|
} else {
|
||||||
|
System.out.println(str.substring(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("\n\n\n");
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void getPlayUrl() {
|
||||||
|
BiliLiveNetApiManager
|
||||||
|
.getInstance()
|
||||||
|
.getApi(new IHttpApiCheckCallback<LiveApi>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(LiveApi api) {
|
||||||
|
String roomId = "32805602";
|
||||||
|
String mid = "68057278";
|
||||||
|
|
||||||
|
// roomId="42062";
|
||||||
|
|
||||||
|
api.getLiveRoomPlayInfo(
|
||||||
|
roomId,
|
||||||
|
LiveProtocol.getAll(),
|
||||||
|
LiveVideoFormat.getAll(),
|
||||||
|
LiveVideoCodec.getAll(),
|
||||||
|
LiveVideoDefinition.ORIGINAL.getValue()
|
||||||
|
).enqueue(new HttpCallback<>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, LiveRoomPlayInfo response, String rawResponse) {
|
||||||
|
LiveRoomPlayInfo.Codec codec = response.getPlayurlInfo().getPlayurl().getStream().get(0).getFormat().get(0).getCodec().get(0);
|
||||||
|
|
||||||
|
LiveRoomConfig config = new LiveRoomConfig();
|
||||||
|
config.setUid("0");
|
||||||
|
config.setRoomId(roomId);
|
||||||
|
config.setMid(mid);
|
||||||
|
config.setLogin(false);
|
||||||
|
WebSocketManager.getInstance().addRoom(config);
|
||||||
|
|
||||||
|
/*String url = codec.getUrlInfo().get(0).getHost() + codec.getBaseUrl() + codec.getUrlInfo().get(0).getExtra();
|
||||||
|
System.out.println("下载url = " + url);
|
||||||
|
api.downloadLive(url).enqueue(new FileCallback<>(response) {
|
||||||
|
@Override
|
||||||
|
public void onStart(LiveRoomPlayInfo bean) {
|
||||||
|
System.out.println("开始下载");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onDownload(Headers headers, LiveRoomPlayInfo bean, long len, long total) {
|
||||||
|
System.out.println("下载中:"+len+"|"+total);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish(LiveRoomPlayInfo bean) {
|
||||||
|
System.out.println("下载结束");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(LiveRoomPlayInfo bean, Throwable throwable) {
|
||||||
|
System.out.println("下载失败");
|
||||||
|
}
|
||||||
|
});*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int code, String error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void login(String username, String password) {
|
||||||
|
BiliLoginNetApiManager.getInstance().login(new HttpCallback<LoginCookie>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, LoginCookie response, String rawResponse) {
|
||||||
|
System.out.println("headers = " + headers + ", code = " + code + ", status = " + status + ", response = " + response + ", rawResponse = " + rawResponse);
|
||||||
|
if (code == BiliLoginNetApiManager.LOGIN_SUCCESS) {
|
||||||
|
BiliBiliLoginDatabase.getInstance().initData(response).close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void getUserInfo() {
|
||||||
|
BiliUserNetApiManager.getInstance().getUserApi(new IHttpApiCheckCallback<UserApi>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(UserApi api) {
|
||||||
|
api.getUserInfo().enqueue(new HttpCallback<UserInfoBean>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, UserInfoBean response, String rawResponse) {
|
||||||
|
System.out.println("response = " + rawResponse);
|
||||||
|
System.out.println(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int code, String error) {
|
||||||
|
System.out.println("code = " + code + ", error = " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
53
biliapi/src/main/java/com/yutou/bili/api/LiveApi.java
Normal file
53
biliapi/src/main/java/com/yutou/bili/api/LiveApi.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package com.yutou.bili.api;
|
||||||
|
|
||||||
|
import com.yutou.bili.bean.live.*;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import com.yutou.okhttp.FileBody;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直播间相关API
|
||||||
|
* <a href="https://socialsisteryi.github.io/bilibili-API-collect/docs/live/info.html#%E8%8E%B7%E5%8F%96%E7%9B%B4%E6%92%AD%E9%97%B4%E4%BF%A1%E6%81%AF">文档地址</a>
|
||||||
|
*/
|
||||||
|
public interface LiveApi {
|
||||||
|
/**
|
||||||
|
* 获取直播间信息
|
||||||
|
* @param roomId 直播间号 必要 可以为短号
|
||||||
|
*/
|
||||||
|
@GET("/room/v1/Room/get_info")
|
||||||
|
Call<HttpBody<LiveRoomInfo>> getRoomInfo(@Query("room_id")String roomId);
|
||||||
|
@GET("/room/v1/Room/getRoomInfoOld")
|
||||||
|
Call<HttpBody<LiveRoomStatus>> getRoomStatus(@Query("mid")String mid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主播信息
|
||||||
|
*/
|
||||||
|
@GET("/live_user/v1/Master/info")
|
||||||
|
Call<HttpBody<MasterInfoBean>> getMasterInfo(@Query("uid")String uid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取直播间信息
|
||||||
|
* @param id 直播间id
|
||||||
|
* @param protocol 直播协议 {@link com.yutou.bili.enums.LiveProtocol}
|
||||||
|
* @param format 格式 {@link com.yutou.bili.enums.LiveVideoFormat}
|
||||||
|
* @param codec 编码 {@link com.yutou.bili.enums.LiveVideoCodec}
|
||||||
|
* @param qn 清晰度 {@link com.yutou.bili.enums.LiveVideoDefinition}
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GET("/xlive/web-room/v2/index/getRoomPlayInfo")
|
||||||
|
Call<HttpBody<LiveRoomPlayInfo>> getLiveRoomPlayInfo(
|
||||||
|
@Query("room_id")String id,
|
||||||
|
@Query("protocol")String protocol,
|
||||||
|
@Query("format")String format,
|
||||||
|
@Query("codec")String codec,
|
||||||
|
@Query("qn")int qn
|
||||||
|
);
|
||||||
|
@Streaming
|
||||||
|
@GET()
|
||||||
|
Call<FileBody<LiveRoomPlayInfo>> downloadLive(@Url String url);
|
||||||
|
|
||||||
|
@GET("/xlive/web-room/v1/index/getDanmuInfo")
|
||||||
|
Call<HttpBody<LiveDanmuInfo>> getLiveRoomDanmuInfo(@Query("id")String id);
|
||||||
|
}
|
||||||
31
biliapi/src/main/java/com/yutou/bili/api/LoginApi.java
Normal file
31
biliapi/src/main/java/com/yutou/bili/api/LoginApi.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package com.yutou.bili.api;
|
||||||
|
|
||||||
|
import com.yutou.bili.bean.login.CheckCookieBean;
|
||||||
|
import com.yutou.bili.bean.login.LoginInfoBean;
|
||||||
|
import com.yutou.bili.bean.login.QRCodeGenerateBean;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.Query;
|
||||||
|
|
||||||
|
public interface LoginApi {
|
||||||
|
/**
|
||||||
|
* 获取登陆二维码
|
||||||
|
*/
|
||||||
|
@GET("/x/passport-login/web/qrcode/generate")
|
||||||
|
Call<HttpBody<QRCodeGenerateBean>> getQRCodeGenerate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过二维码登录
|
||||||
|
*/
|
||||||
|
@GET("/x/passport-login/web/qrcode/poll")
|
||||||
|
Call<HttpBody<LoginInfoBean>> loginQRCode(@Query("qrcode_key") String qrcode_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查cookie是否有效,太麻烦了以后做
|
||||||
|
*/
|
||||||
|
@GET("x/passport-login/web/cookie/info")
|
||||||
|
Call<HttpBody<CheckCookieBean>> checkCookie();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
16
biliapi/src/main/java/com/yutou/bili/api/UserApi.java
Normal file
16
biliapi/src/main/java/com/yutou/bili/api/UserApi.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package com.yutou.bili.api;
|
||||||
|
|
||||||
|
import com.yutou.bili.bean.live.SpiBean;
|
||||||
|
import com.yutou.bili.bean.login.UserInfoBean;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
|
||||||
|
public interface UserApi {
|
||||||
|
@GET("/x/web-interface/nav")
|
||||||
|
Call<HttpBody<UserInfoBean>> getUserInfo();
|
||||||
|
|
||||||
|
|
||||||
|
@GET("/x/frontend/finger/spi")
|
||||||
|
Call<HttpBody<SpiBean>> getFingerSpi();
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.yutou.bili.bean.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LiveDanmuInfo {
|
||||||
|
@JSONField(name = "group")
|
||||||
|
private String group;
|
||||||
|
|
||||||
|
@JSONField(name = "business_id")
|
||||||
|
private int businessId;
|
||||||
|
|
||||||
|
@JSONField(name = "refresh_row_factor")
|
||||||
|
private double refreshRowFactor;
|
||||||
|
|
||||||
|
@JSONField(name = "refresh_rate")
|
||||||
|
private int refreshRate;
|
||||||
|
|
||||||
|
@JSONField(name = "max_delay")
|
||||||
|
private int maxDelay;
|
||||||
|
|
||||||
|
@JSONField(name = "token")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@JSONField(name = "host_list")
|
||||||
|
private List<Host> hostList;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Host {
|
||||||
|
|
||||||
|
@JSONField(name = "host")
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
@JSONField(name = "port")
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
@JSONField(name = "wss_port")
|
||||||
|
private int wssPort;
|
||||||
|
|
||||||
|
@JSONField(name = "ws_port")
|
||||||
|
private int wsPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.yutou.bili.bean.live;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LiveRoomConfig {
|
||||||
|
String uid;
|
||||||
|
String roomId;
|
||||||
|
String mid;//真实房间id
|
||||||
|
boolean isLogin;
|
||||||
|
LiveDanmuInfo liveInfo;
|
||||||
|
|
||||||
|
}
|
||||||
234
biliapi/src/main/java/com/yutou/bili/bean/live/LiveRoomInfo.java
Normal file
234
biliapi/src/main/java/com/yutou/bili/bean/live/LiveRoomInfo.java
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
package com.yutou.bili.bean.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LiveRoomInfo {
|
||||||
|
@JSONField(name = "uid")
|
||||||
|
private int uid;
|
||||||
|
|
||||||
|
@JSONField(name = "room_id")
|
||||||
|
private int roomId;
|
||||||
|
|
||||||
|
@JSONField(name = "short_id")
|
||||||
|
private int shortId;
|
||||||
|
|
||||||
|
@JSONField(name = "attention")
|
||||||
|
private int attention;
|
||||||
|
|
||||||
|
@JSONField(name = "online")
|
||||||
|
private int online;
|
||||||
|
|
||||||
|
@JSONField(name = "is_portrait")
|
||||||
|
private boolean isPortrait;
|
||||||
|
|
||||||
|
@JSONField(name = "description")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@JSONField(name = "live_status")
|
||||||
|
private int liveStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "area_id")
|
||||||
|
private int areaId;
|
||||||
|
|
||||||
|
@JSONField(name = "parent_area_id")
|
||||||
|
private int parentAreaId;
|
||||||
|
|
||||||
|
@JSONField(name = "parent_area_name")
|
||||||
|
private String parentAreaName;
|
||||||
|
|
||||||
|
@JSONField(name = "old_area_id")
|
||||||
|
private int oldAreaId;
|
||||||
|
|
||||||
|
@JSONField(name = "background")
|
||||||
|
private String background;
|
||||||
|
|
||||||
|
@JSONField(name = "title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@JSONField(name = "user_cover")
|
||||||
|
private String userCover;
|
||||||
|
|
||||||
|
@JSONField(name = "keyframe")
|
||||||
|
private String keyframe;
|
||||||
|
|
||||||
|
@JSONField(name = "is_strict_room")
|
||||||
|
private boolean isStrictRoom;
|
||||||
|
|
||||||
|
@JSONField(name = "live_time")
|
||||||
|
private String liveTime;
|
||||||
|
|
||||||
|
@JSONField(name = "tags")
|
||||||
|
private String tags;
|
||||||
|
|
||||||
|
@JSONField(name = "is_anchor")
|
||||||
|
private int isAnchor;
|
||||||
|
|
||||||
|
@JSONField(name = "room_silent_type")
|
||||||
|
private String roomSilentType;
|
||||||
|
|
||||||
|
@JSONField(name = "room_silent_level")
|
||||||
|
private int roomSilentLevel;
|
||||||
|
|
||||||
|
@JSONField(name = "room_silent_second")
|
||||||
|
private int roomSilentSecond;
|
||||||
|
|
||||||
|
@JSONField(name = "area_name")
|
||||||
|
private String areaName;
|
||||||
|
|
||||||
|
@JSONField(name = "pendants")
|
||||||
|
private String pendants;
|
||||||
|
|
||||||
|
@JSONField(name = "area_pendants")
|
||||||
|
private String areaPendants;
|
||||||
|
|
||||||
|
@JSONField(name = "hot_words")
|
||||||
|
private List<String> hotWords;
|
||||||
|
|
||||||
|
@JSONField(name = "hot_words_status")
|
||||||
|
private int hotWordsStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "verify")
|
||||||
|
private String verify;
|
||||||
|
|
||||||
|
@JSONField(name = "new_pendants")
|
||||||
|
private NewPendants newPendants;
|
||||||
|
|
||||||
|
@JSONField(name = "up_session")
|
||||||
|
private String upSession;
|
||||||
|
|
||||||
|
@JSONField(name = "pk_status")
|
||||||
|
private int pkStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "pk_id")
|
||||||
|
private int pkId;
|
||||||
|
|
||||||
|
@JSONField(name = "battle_id")
|
||||||
|
private int battleId;
|
||||||
|
|
||||||
|
@JSONField(name = "allow_change_area_time")
|
||||||
|
private int allowChangeAreaTime;
|
||||||
|
|
||||||
|
@JSONField(name = "allow_upload_cover_time")
|
||||||
|
private int allowUploadCoverTime;
|
||||||
|
|
||||||
|
@JSONField(name = "studio_info")
|
||||||
|
private StudioInfo studioInfo;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class NewPendants {
|
||||||
|
@JSONField(name = "frame")
|
||||||
|
private Frame frame;
|
||||||
|
|
||||||
|
@JSONField(name = "badge")
|
||||||
|
private Badge badge;
|
||||||
|
|
||||||
|
@JSONField(name = "mobile_frame")
|
||||||
|
private MobileFrame mobileFrame;
|
||||||
|
@JSONField(name = "mobile_badge")
|
||||||
|
private MobileBadge mobileBadge;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Frame {
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@JSONField(name = "value")
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@JSONField(name = "position")
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
@JSONField(name = "area")
|
||||||
|
private int area;
|
||||||
|
|
||||||
|
@JSONField(name = "area_old")
|
||||||
|
private int areaOld;
|
||||||
|
|
||||||
|
@JSONField(name = "bg_color")
|
||||||
|
private String bgColor;
|
||||||
|
|
||||||
|
@JSONField(name = "bg_pic")
|
||||||
|
private String bgPic;
|
||||||
|
|
||||||
|
@JSONField(name = "use_old_area")
|
||||||
|
private boolean useOldArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Badge {
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@JSONField(name = "position")
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
@JSONField(name = "value")
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class MobileFrame {
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@JSONField(name = "value")
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@JSONField(name = "position")
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
@JSONField(name = "area")
|
||||||
|
private int area;
|
||||||
|
|
||||||
|
@JSONField(name = "area_old")
|
||||||
|
private int areaOld;
|
||||||
|
|
||||||
|
@JSONField(name = "bg_color")
|
||||||
|
private String bgColor;
|
||||||
|
|
||||||
|
@JSONField(name = "bg_pic")
|
||||||
|
private String bgPic;
|
||||||
|
|
||||||
|
@JSONField(name = "use_old_area")
|
||||||
|
private boolean useOldArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class MobileBadge {
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@JSONField(name = "position")
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
@JSONField(name = "value")
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class StudioInfo {
|
||||||
|
@JSONField(name = "status")
|
||||||
|
private int status;
|
||||||
|
|
||||||
|
@JSONField(name = "master_list")
|
||||||
|
private List<String> masterList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
package com.yutou.bili.bean.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class LiveRoomPlayInfo extends BaseBean {
|
||||||
|
@JSONField(name = "room_id")
|
||||||
|
private int roomId;
|
||||||
|
|
||||||
|
@JSONField(name = "short_id")
|
||||||
|
private int shortId;
|
||||||
|
|
||||||
|
@JSONField(name = "uid")
|
||||||
|
private int uid;
|
||||||
|
|
||||||
|
@JSONField(name = "is_hidden")
|
||||||
|
private boolean isHidden;
|
||||||
|
|
||||||
|
@JSONField(name = "is_locked")
|
||||||
|
private boolean isLocked;
|
||||||
|
|
||||||
|
@JSONField(name = "is_portrait")
|
||||||
|
private boolean isPortrait;
|
||||||
|
|
||||||
|
@JSONField(name = "live_status")
|
||||||
|
private int liveStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "hidden_till")
|
||||||
|
private int hiddenTill;
|
||||||
|
|
||||||
|
@JSONField(name = "lock_till")
|
||||||
|
private int lockTill;
|
||||||
|
|
||||||
|
@JSONField(name = "encrypted")
|
||||||
|
private boolean encrypted;
|
||||||
|
|
||||||
|
@JSONField(name = "pwd_verified")
|
||||||
|
private boolean pwdVerified;
|
||||||
|
|
||||||
|
@JSONField(name = "live_time")
|
||||||
|
private int liveTime;
|
||||||
|
|
||||||
|
@JSONField(name = "room_shield")
|
||||||
|
private int roomShield;
|
||||||
|
|
||||||
|
@JSONField(name = "all_special_types")
|
||||||
|
private List<Integer> allSpecialTypes;
|
||||||
|
|
||||||
|
@JSONField(name = "playurl_info")
|
||||||
|
private PlayurlInfo playurlInfo;
|
||||||
|
|
||||||
|
@JSONField(name = "official_type")
|
||||||
|
private int officialType;
|
||||||
|
|
||||||
|
@JSONField(name = "official_room_id")
|
||||||
|
private int officialRoomId;
|
||||||
|
|
||||||
|
@JSONField(name = "risk_with_delay")
|
||||||
|
private int riskWithDelay;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class PlayurlInfo {
|
||||||
|
@JSONField(name = "conf_json")
|
||||||
|
private String confJson;
|
||||||
|
|
||||||
|
@JSONField(name = "playurl")
|
||||||
|
private Playurl playurl;
|
||||||
|
|
||||||
|
@JSONField(name = "dolby_qn")
|
||||||
|
private Integer dolbyQn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Playurl {
|
||||||
|
@JSONField(name = "cid")
|
||||||
|
private int cid;
|
||||||
|
|
||||||
|
@JSONField(name = "g_qn_desc")
|
||||||
|
private List<QnDesc> gQnDesc;
|
||||||
|
|
||||||
|
@JSONField(name = "stream")
|
||||||
|
private List<Stream> stream;
|
||||||
|
|
||||||
|
@JSONField(name = "p2p_data")
|
||||||
|
private P2pData p2pData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class QnDesc {
|
||||||
|
@JSONField(name = "qn")
|
||||||
|
private int qn;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
@JSONField(name = "hdr_desc")
|
||||||
|
private String hdrDesc;
|
||||||
|
|
||||||
|
@JSONField(name = "attr_desc")
|
||||||
|
private Object attrDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Stream {
|
||||||
|
@JSONField(name = "protocol_name")
|
||||||
|
private String protocolName;
|
||||||
|
|
||||||
|
@JSONField(name = "format")
|
||||||
|
private List<Format> format;
|
||||||
|
|
||||||
|
@JSONField(name = "p2p_type")
|
||||||
|
private int p2pType;
|
||||||
|
|
||||||
|
@JSONField(name = "free_type")
|
||||||
|
private int freeType;
|
||||||
|
|
||||||
|
@JSONField(name = "mid")
|
||||||
|
private int mid;
|
||||||
|
|
||||||
|
@JSONField(name = "sid")
|
||||||
|
private String sid;
|
||||||
|
|
||||||
|
@JSONField(name = "chash")
|
||||||
|
private int chash;
|
||||||
|
|
||||||
|
@JSONField(name = "bmt")
|
||||||
|
private int bmt;
|
||||||
|
|
||||||
|
@JSONField(name = "sche")
|
||||||
|
private String sche;
|
||||||
|
|
||||||
|
@JSONField(name = "score")
|
||||||
|
private int score;
|
||||||
|
|
||||||
|
@JSONField(name = "pp")
|
||||||
|
private String pp;
|
||||||
|
|
||||||
|
@JSONField(name = "source")
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
@JSONField(name = "trace")
|
||||||
|
private int trace;
|
||||||
|
|
||||||
|
@JSONField(name = "site")
|
||||||
|
private String site;
|
||||||
|
@JSONField(name = "zoneid_l")
|
||||||
|
private int zoneidL;
|
||||||
|
|
||||||
|
@JSONField(name = "sid_l")
|
||||||
|
private String sidL;
|
||||||
|
|
||||||
|
@JSONField(name = "order")
|
||||||
|
private int order;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Format {
|
||||||
|
@JSONField(name = "format_name")
|
||||||
|
private String formatName;
|
||||||
|
|
||||||
|
@JSONField(name = "codec")
|
||||||
|
private List<Codec> codec;
|
||||||
|
|
||||||
|
@JSONField(name = "hdr_qn")
|
||||||
|
private Integer hdrQn;
|
||||||
|
|
||||||
|
@JSONField(name = "dolby_type")
|
||||||
|
private int dolbyType;
|
||||||
|
|
||||||
|
@JSONField(name = "attr_name")
|
||||||
|
private String attrName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Codec {
|
||||||
|
@JSONField(name = "codec_name")
|
||||||
|
private String codecName;
|
||||||
|
|
||||||
|
@JSONField(name = "current_qn")
|
||||||
|
private int currentQn;
|
||||||
|
|
||||||
|
@JSONField(name = "accept_qn")
|
||||||
|
private List<Integer> acceptQn;
|
||||||
|
|
||||||
|
@JSONField(name = "base_url")
|
||||||
|
private String baseUrl;
|
||||||
|
|
||||||
|
@JSONField(name = "url_info")
|
||||||
|
private List<UrlInfo> urlInfo;
|
||||||
|
|
||||||
|
@JSONField(name = "hdr_desc")
|
||||||
|
private String hdrDesc;
|
||||||
|
|
||||||
|
@JSONField(name = "attr_desc")
|
||||||
|
private Object attrDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class UrlInfo {
|
||||||
|
@JSONField(name = "host")
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
@JSONField(name = "extra")
|
||||||
|
private String extra;
|
||||||
|
|
||||||
|
@JSONField(name = "stream_ttl")
|
||||||
|
private int streamTtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class P2pData {
|
||||||
|
@JSONField(name = "p2p")
|
||||||
|
private boolean p2p;
|
||||||
|
|
||||||
|
@JSONField(name = "p2p_type")
|
||||||
|
private int p2pType;
|
||||||
|
|
||||||
|
@JSONField(name = "m_p2p")
|
||||||
|
private boolean mP2p;
|
||||||
|
|
||||||
|
@JSONField(name = "m_servers")
|
||||||
|
private List<String> mServers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.yutou.bili.bean.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LiveRoomStatus {
|
||||||
|
@JSONField(name = "roomStatus")
|
||||||
|
private int roomStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "roundStatus")
|
||||||
|
private int roundStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "liveStatus")
|
||||||
|
private int liveStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "url")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@JSONField(name = "title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@JSONField(name = "cover")
|
||||||
|
private String cover;
|
||||||
|
|
||||||
|
@JSONField(name = "online")
|
||||||
|
private int online;
|
||||||
|
|
||||||
|
@JSONField(name = "roomid")
|
||||||
|
private int roomid;
|
||||||
|
|
||||||
|
@JSONField(name = "broadcast_type")
|
||||||
|
private int broadcastType;
|
||||||
|
|
||||||
|
@JSONField(name = "online_hidden")
|
||||||
|
private int onlineHidden;
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.yutou.bili.bean.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class MasterInfoBean extends BaseBean {
|
||||||
|
@JSONField(name = "info")
|
||||||
|
private Info info;
|
||||||
|
|
||||||
|
@JSONField(name = "exp")
|
||||||
|
private Exp exp;
|
||||||
|
|
||||||
|
@JSONField(name = "follower_num")
|
||||||
|
private int followerNum;
|
||||||
|
|
||||||
|
@JSONField(name = "room_id")
|
||||||
|
private int roomId;
|
||||||
|
|
||||||
|
@JSONField(name = "medal_name")
|
||||||
|
private String medalName;
|
||||||
|
|
||||||
|
@JSONField(name = "glory_count")
|
||||||
|
private int gloryCount;
|
||||||
|
|
||||||
|
@JSONField(name = "pendant")
|
||||||
|
private String pendant;
|
||||||
|
|
||||||
|
@JSONField(name = "link_group_num")
|
||||||
|
private int linkGroupNum;
|
||||||
|
|
||||||
|
@JSONField(name = "room_news")
|
||||||
|
private RoomNews roomNews;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Info {
|
||||||
|
@JSONField(name = "uid")
|
||||||
|
private int uid;
|
||||||
|
|
||||||
|
@JSONField(name = "uname")
|
||||||
|
private String uname;
|
||||||
|
|
||||||
|
@JSONField(name = "face")
|
||||||
|
private String face;
|
||||||
|
|
||||||
|
@JSONField(name = "official_verify")
|
||||||
|
private OfficialVerify officialVerify;
|
||||||
|
|
||||||
|
@JSONField(name = "gender")
|
||||||
|
private int gender;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Exp {
|
||||||
|
@JSONField(name = "master_level")
|
||||||
|
private MasterLevel masterLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class MasterLevel {
|
||||||
|
@JSONField(name = "level")
|
||||||
|
private int level;
|
||||||
|
|
||||||
|
@JSONField(name = "color")
|
||||||
|
private int color;
|
||||||
|
|
||||||
|
@JSONField(name = "current")
|
||||||
|
private List<Integer> current;
|
||||||
|
|
||||||
|
@JSONField(name = "next")
|
||||||
|
private List<Integer> next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class OfficialVerify {
|
||||||
|
@JSONField(name = "type")
|
||||||
|
private int type;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RoomNews {
|
||||||
|
@JSONField(name = "content")
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@JSONField(name = "ctime")
|
||||||
|
private String ctime;
|
||||||
|
|
||||||
|
@JSONField(name = "ctime_text")
|
||||||
|
private String ctimeText;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
biliapi/src/main/java/com/yutou/bili/bean/live/SpiBean.java
Normal file
12
biliapi/src/main/java/com/yutou/bili/bean/live/SpiBean.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package com.yutou.bili.bean.live;
|
||||||
|
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class SpiBean extends BaseBean {
|
||||||
|
private String b_3;
|
||||||
|
private String b_4;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.yutou.bili.bean.login;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class CheckCookieBean extends BaseBean {
|
||||||
|
@JSONField(name = "refresh")
|
||||||
|
boolean refresh;
|
||||||
|
@JSONField(name = "timestamp")
|
||||||
|
long timestamp;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.yutou.bili.bean.login;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import com.yutou.databases.AbsDatabasesBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class LoginCookie extends AbsDatabasesBean {
|
||||||
|
@JSONField(name = "SESSDATA")
|
||||||
|
String sessdta;
|
||||||
|
@JSONField(name = "Path")
|
||||||
|
String path;
|
||||||
|
@JSONField(name = "DedeUserID")
|
||||||
|
String dedeUserID;
|
||||||
|
@JSONField(name = "DedeUserID__ckMd5")
|
||||||
|
String dedeUserIDCkMd5;
|
||||||
|
@JSONField(name = "bili_jct")
|
||||||
|
String biliJct;
|
||||||
|
@JSONField(name = "Expires")
|
||||||
|
String expires;
|
||||||
|
@JSONField(name = "Domain")
|
||||||
|
String domain;
|
||||||
|
@JSONField(name = "sid")
|
||||||
|
String sid;
|
||||||
|
@JSONField(name = "gourl")
|
||||||
|
String gourl;
|
||||||
|
|
||||||
|
public LoginCookie() {
|
||||||
|
setTableName("login_cookie");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.yutou.bili.bean.login;
|
||||||
|
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class LoginInfoBean extends BaseBean {
|
||||||
|
private String url;
|
||||||
|
private String refresh_token;
|
||||||
|
private long timestamp;
|
||||||
|
private int code;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.yutou.bili.bean.login;
|
||||||
|
|
||||||
|
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class QRCodeGenerateBean extends BaseBean {
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
private String qrcode_key;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
package com.yutou.bili.bean.login;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class UserInfoBean extends BaseBean {
|
||||||
|
|
||||||
|
@JSONField(name = "isLogin")
|
||||||
|
private boolean isLogin;
|
||||||
|
|
||||||
|
@JSONField(name = "email_verified")
|
||||||
|
private int emailVerified;
|
||||||
|
|
||||||
|
@JSONField(name = "face")
|
||||||
|
private String face;
|
||||||
|
|
||||||
|
@JSONField(name = "face_nft")
|
||||||
|
private int faceNft;
|
||||||
|
|
||||||
|
@JSONField(name = "face_nft_type")
|
||||||
|
private int faceNftType;
|
||||||
|
|
||||||
|
@JSONField(name = "level_info")
|
||||||
|
private LevelInfo levelInfo;
|
||||||
|
|
||||||
|
@JSONField(name = "mid")
|
||||||
|
private long mid;
|
||||||
|
|
||||||
|
@JSONField(name = "mobile_verified")
|
||||||
|
private int mobileVerified;
|
||||||
|
|
||||||
|
@JSONField(name = "money")
|
||||||
|
private double money;
|
||||||
|
|
||||||
|
@JSONField(name = "moral")
|
||||||
|
private int moral;
|
||||||
|
|
||||||
|
@JSONField(name = "official")
|
||||||
|
private Official official;
|
||||||
|
|
||||||
|
@JSONField(name = "officialVerify")
|
||||||
|
private OfficialVerify officialVerify;
|
||||||
|
|
||||||
|
@JSONField(name = "pendant")
|
||||||
|
private Pendant pendant;
|
||||||
|
|
||||||
|
@JSONField(name = "scores")
|
||||||
|
private int scores;
|
||||||
|
|
||||||
|
@JSONField(name = "uname")
|
||||||
|
private String uname;
|
||||||
|
|
||||||
|
@JSONField(name = "vipDueDate")
|
||||||
|
private Date vipDueDate;
|
||||||
|
|
||||||
|
@JSONField(name = "vipStatus")
|
||||||
|
private int vipStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "vipType")
|
||||||
|
private int vipType;
|
||||||
|
|
||||||
|
@JSONField(name = "vip_pay_type")
|
||||||
|
private int vipPayType;
|
||||||
|
|
||||||
|
@JSONField(name = "vip_theme_type")
|
||||||
|
private int vipThemeType;
|
||||||
|
|
||||||
|
@JSONField(name = "vip_label")
|
||||||
|
private VipLabel vipLabel;
|
||||||
|
|
||||||
|
@JSONField(name = "vip_avatar_subscript")
|
||||||
|
private int vipAvatarSubscript;
|
||||||
|
|
||||||
|
@JSONField(name = "vip_nickname_color")
|
||||||
|
private String vipNicknameColor;
|
||||||
|
|
||||||
|
@JSONField(name = "vip")
|
||||||
|
private Vip vip;
|
||||||
|
|
||||||
|
@JSONField(name = "wallet")
|
||||||
|
private Wallet wallet;
|
||||||
|
|
||||||
|
@JSONField(name = "has_shop")
|
||||||
|
private boolean hasShop;
|
||||||
|
|
||||||
|
@JSONField(name = "shop_url")
|
||||||
|
private String shopUrl;
|
||||||
|
|
||||||
|
@JSONField(name = "allowance_count")
|
||||||
|
private int allowanceCount;
|
||||||
|
|
||||||
|
@JSONField(name = "answer_status")
|
||||||
|
private int answerStatus;
|
||||||
|
|
||||||
|
@JSONField(name = "is_senior_member")
|
||||||
|
private boolean isSeniorMember;
|
||||||
|
|
||||||
|
@JSONField(name = "wbi_img")
|
||||||
|
private WbiImg wbiImg;
|
||||||
|
|
||||||
|
@JSONField(name = "is_jury")
|
||||||
|
private boolean isJury;
|
||||||
|
|
||||||
|
// 省略了getters和setters
|
||||||
|
|
||||||
|
// level_info的内部数据结构
|
||||||
|
@Data
|
||||||
|
public static class LevelInfo {
|
||||||
|
@JSONField(name = "current_level")
|
||||||
|
private int currentLevel;
|
||||||
|
|
||||||
|
@JSONField(name = "current_min")
|
||||||
|
private int currentMin;
|
||||||
|
|
||||||
|
@JSONField(name = "current_exp")
|
||||||
|
private int currentExp;
|
||||||
|
|
||||||
|
@JSONField(name = "next_exp")
|
||||||
|
private String nextExp;
|
||||||
|
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
|
||||||
|
// official的结构
|
||||||
|
@Data
|
||||||
|
public static class Official {
|
||||||
|
@JSONField(name = "role")
|
||||||
|
private int role;
|
||||||
|
|
||||||
|
@JSONField(name = "title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
@JSONField(name = "type")
|
||||||
|
private int type;
|
||||||
|
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
|
||||||
|
// officialVerify的结构
|
||||||
|
@Data
|
||||||
|
public static class OfficialVerify {
|
||||||
|
@JSONField(name = "type")
|
||||||
|
private int type;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
|
||||||
|
// pendant的结构
|
||||||
|
@Data
|
||||||
|
public static class Pendant {
|
||||||
|
@JSONField(name = "pid")
|
||||||
|
private int pid;
|
||||||
|
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@JSONField(name = "image")
|
||||||
|
private String image;
|
||||||
|
|
||||||
|
@JSONField(name = "expire")
|
||||||
|
private int expire;
|
||||||
|
|
||||||
|
@JSONField(name = "image_enhance")
|
||||||
|
private String imageEnhance;
|
||||||
|
|
||||||
|
@JSONField(name = "image_enhance_frame")
|
||||||
|
private String imageEnhanceFrame;
|
||||||
|
|
||||||
|
@JSONField(name = "n_pid")
|
||||||
|
private int nPid;
|
||||||
|
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
|
||||||
|
// vipLabel的结构
|
||||||
|
@Data
|
||||||
|
public static class VipLabel {
|
||||||
|
@JSONField(name = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@JSONField(name = "text")
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
@JSONField(name = "label_theme")
|
||||||
|
private String labelTheme;
|
||||||
|
|
||||||
|
@JSONField(name = "text_color")
|
||||||
|
private String textColor;
|
||||||
|
|
||||||
|
@JSONField(name = "bg_style")
|
||||||
|
private String bgStyle;
|
||||||
|
|
||||||
|
@JSONField(name = "bg_color")
|
||||||
|
private String bgColor;
|
||||||
|
|
||||||
|
@JSONField(name = "border_color")
|
||||||
|
private String borderColor;
|
||||||
|
|
||||||
|
@JSONField(name = "use_img_label")
|
||||||
|
private boolean useImgLabel;
|
||||||
|
|
||||||
|
@JSONField(name = "img_label_uri_hans")
|
||||||
|
private String imgLabelUriHans;
|
||||||
|
|
||||||
|
@JSONField(name = "img_label_uri_hant")
|
||||||
|
private String imgLabelUriHant;
|
||||||
|
|
||||||
|
@JSONField(name = "img_label_uri_hans_static")
|
||||||
|
private String imgLabelUriHansStatic;
|
||||||
|
|
||||||
|
@JSONField(name = "img_label_uri_hant_static")
|
||||||
|
private String imgLabelUriHantStatic;
|
||||||
|
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
|
||||||
|
// vip的结构,和vipLabel类似
|
||||||
|
@Data
|
||||||
|
public static class Vip {
|
||||||
|
@JSONField(name = "type")
|
||||||
|
private int type;
|
||||||
|
|
||||||
|
@JSONField(name = "status")
|
||||||
|
private int status;
|
||||||
|
|
||||||
|
@JSONField(name = "due_date")
|
||||||
|
private Date dueDate;
|
||||||
|
|
||||||
|
@JSONField(name = "vip_pay_type")
|
||||||
|
private int vipPayType;
|
||||||
|
|
||||||
|
@JSONField(name = "theme_type")
|
||||||
|
private int themeType;
|
||||||
|
|
||||||
|
@JSONField(name = "label")
|
||||||
|
private VipLabel label;
|
||||||
|
|
||||||
|
@JSONField(name = "avatar_subscript")
|
||||||
|
private int avatarSubscript;
|
||||||
|
|
||||||
|
@JSONField(name = "nickname_color")
|
||||||
|
private String nicknameColor;
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
|
||||||
|
// wallet的结构
|
||||||
|
@Data
|
||||||
|
public static class Wallet {
|
||||||
|
@JSONField(name = "mid")
|
||||||
|
private long mid;
|
||||||
|
|
||||||
|
@JSONField(name = "bcoin_balance")
|
||||||
|
private int bcoinBalance;
|
||||||
|
|
||||||
|
@JSONField(name = "coupon_balance")
|
||||||
|
private int couponBalance;
|
||||||
|
|
||||||
|
@JSONField(name = "coupon_due_time")
|
||||||
|
private int couponDueTime;
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
|
||||||
|
// WbiImg的结构
|
||||||
|
@Data
|
||||||
|
public static class WbiImg {
|
||||||
|
@JSONField(name = "img_url")
|
||||||
|
private String imgUrl;
|
||||||
|
|
||||||
|
@JSONField(name = "sub_url")
|
||||||
|
private String subUrl;
|
||||||
|
|
||||||
|
// getters and setters
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.yutou.bili.bean.websocket;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WebSocketBody {
|
||||||
|
List<JSONObject> bodyList;
|
||||||
|
|
||||||
|
public WebSocketBody(byte[] bytes) {
|
||||||
|
bodyList = new ArrayList<>();
|
||||||
|
addBody(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addBody(byte[] bytes, int offset) {
|
||||||
|
if (offset >= bytes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] headerByte = new byte[16];
|
||||||
|
System.arraycopy(bytes, offset, headerByte, 0, headerByte.length);
|
||||||
|
WebSocketHeader header = new WebSocketHeader(headerByte);
|
||||||
|
byte[] data = new byte[header.getDataSize() - header.getHeaderSize()];
|
||||||
|
System.arraycopy(bytes, offset + header.getHeaderSize(), data, 0, data.length);
|
||||||
|
try {
|
||||||
|
bodyList.add(JSONObject.parseObject(new String(data)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(header + "|" + new String(data));
|
||||||
|
}
|
||||||
|
addBody(bytes, offset + header.dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.yutou.bili.bean.websocket;
|
||||||
|
|
||||||
|
import com.yutou.bili.utils.BytesUtils;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WebSocketHeader {
|
||||||
|
int dataSize;
|
||||||
|
int agree;
|
||||||
|
int headerSize;
|
||||||
|
int cmdData;
|
||||||
|
|
||||||
|
public WebSocketHeader(byte[] bytes) {
|
||||||
|
byte[] size = new byte[4];
|
||||||
|
byte[] header = new byte[4];
|
||||||
|
byte[] cmd = new byte[4];
|
||||||
|
byte[] agreement = new byte[4];
|
||||||
|
System.arraycopy(bytes, 0, size, 0, 4);
|
||||||
|
System.arraycopy(bytes, 8, cmd, 0, 4);
|
||||||
|
System.arraycopy(bytes, 6, agreement, 2, 2);
|
||||||
|
System.arraycopy(bytes, 4, header, 2, 2);
|
||||||
|
dataSize = BytesUtils.bytesToInt2(size, 0);
|
||||||
|
agree = BytesUtils.bytesToInt2(agreement, 0);
|
||||||
|
headerSize = BytesUtils.bytesToInt2(header, 0);
|
||||||
|
cmdData = BytesUtils.bytesToInt2(cmd, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.utils.Log;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹幕信息
|
||||||
|
* <a href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/message_stream.md#%E5%BC%B9%E5%B9%95">弹幕</a>
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class WSDanmuData extends WSData {
|
||||||
|
private String dm_v2;
|
||||||
|
private int id;
|
||||||
|
private int model;// 1~3 滚动弹幕 4 底端弹幕 5 顶端弹幕 6 逆向弹幕 7 精准定位 8 高级弹幕
|
||||||
|
private int fontSize;
|
||||||
|
private String fontColor;
|
||||||
|
private long time;
|
||||||
|
private String uCode;
|
||||||
|
private String danmu;
|
||||||
|
private long uid;
|
||||||
|
private String uname;
|
||||||
|
private WSUserMedal medal;
|
||||||
|
|
||||||
|
public WSDanmuData(JSONObject json) {
|
||||||
|
super(json);
|
||||||
|
JSONArray infoData = json.getJSONArray("info");
|
||||||
|
setModel(infoData.getJSONArray(0).getInteger(1));
|
||||||
|
setFontSize(infoData.getJSONArray(0).getInteger(2));
|
||||||
|
setFontColor(Integer.toHexString(infoData.getJSONArray(0).getInteger(3)));
|
||||||
|
setTime(infoData.getJSONArray(0).getLong(4));
|
||||||
|
setUCode(infoData.getJSONArray(0).getString(7));
|
||||||
|
setDanmu(infoData.getString(1));
|
||||||
|
setUid(infoData.getJSONArray(2).getInteger(0));
|
||||||
|
setUname(infoData.getJSONArray(2).getString(1));
|
||||||
|
try {
|
||||||
|
medal = WSUserMedal.create(infoData.getJSONArray(3));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.i("弹幕信息解析失败:" + json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "弹幕 = " + "用户:" + getUname() + " 发送了: " + getDanmu() +" | json = "+jsonSrc;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class WSData implements Serializable {
|
||||||
|
public String cmd;
|
||||||
|
public String jsonSrc;
|
||||||
|
public long ws_timer;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public WSData() {
|
||||||
|
throw new NullPointerException("需要传入json");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "WSData{" +
|
||||||
|
"cmd='" + cmd + '\'' +
|
||||||
|
", jsonSrc='" + jsonSrc + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public WSData(JSONObject json) {
|
||||||
|
this.cmd = json.getString("cmd");
|
||||||
|
ws_timer = System.currentTimeMillis();
|
||||||
|
this.jsonSrc = json.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WSData parse(JSONObject json) {
|
||||||
|
String cmd = json.getString("cmd");
|
||||||
|
return switch (cmd) {
|
||||||
|
case "DANMU_MSG" -> new WSDanmuData(json);
|
||||||
|
case "DM_INTERACTION" -> new WSDmInteraction(json);
|
||||||
|
case "SEND_GIFT" -> new WSSendGift(json);
|
||||||
|
case "INTERACT_WORD" -> new WSInteractWord(json);
|
||||||
|
case "GUARD_BUY" -> new WSGuardBuy(json);
|
||||||
|
default -> new WSData(json);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连续弹幕消息
|
||||||
|
* <a href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/message_stream.md#%E8%BF%9E%E7%BB%AD%E5%BC%B9%E5%B9%95%E6%B6%88%E6%81%AF">连续弹幕消息</a>
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class WSDmInteraction extends WSData{
|
||||||
|
public final static int TYPE_ZAN=106;//点赞
|
||||||
|
public final static int TYPE_SHARE=105;//分享
|
||||||
|
public final static int TYPE_DANMU=102;//弹幕
|
||||||
|
private ComboData combo;
|
||||||
|
private int type;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JSONObject json=JSONObject.parseObject("{\"cmd\":\"DM_INTERACTION\",\"data\":{\"data\":\"{\\\"fade_duration\\\":10000,\\\"cnt\\\":5,\\\"card_appear_interval\\\":0,\\\"suffix_text\\\":\\\"人正在点赞\\\",\\\"reset_cnt\\\":1,\\\"display_flag\\\":1}\",\"dmscore\":36,\"id\":53793047788032,\"status\":4,\"type\":106}}");
|
||||||
|
WSDmInteraction wsDmInteraction=new WSDmInteraction(json);
|
||||||
|
System.out.println(wsDmInteraction);
|
||||||
|
}
|
||||||
|
public WSDmInteraction(JSONObject json) {
|
||||||
|
super(json);
|
||||||
|
JSONObject data=json.getJSONObject("data");
|
||||||
|
JSONObject comboJson=JSONObject.parseObject(data.getString("data"));
|
||||||
|
combo=JSONObject.parseObject(data.getString("data"), ComboData.class);
|
||||||
|
type=data.getIntValue("type");
|
||||||
|
if(type==106){
|
||||||
|
combo.setContent(comboJson.getString("suffix_text"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ComboData implements Serializable {
|
||||||
|
String content;
|
||||||
|
String guide;
|
||||||
|
int cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "WSDmInteraction{" +
|
||||||
|
"combo=" + combo +
|
||||||
|
", cmd='" + cmd + '\'' +
|
||||||
|
", jsonSrc='" + jsonSrc + '\'' +
|
||||||
|
", ws_timer=" + ws_timer +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 大航海购买
|
||||||
|
* <a href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/message_stream.md#%E4%B8%8A%E8%88%B0%E9%80%9A%E7%9F%A5">上舰通知</a>
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class WSGuardBuy extends WSData{
|
||||||
|
private long uid;
|
||||||
|
private String username;
|
||||||
|
private long guardLevel;
|
||||||
|
private long num;
|
||||||
|
private long price;
|
||||||
|
private long giftID;
|
||||||
|
private String giftName;
|
||||||
|
private long startTime;
|
||||||
|
private long endTime;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JSONObject json=JSONObject.parseObject("{\"cmd\":\"GUARD_BUY\",\"data\":{\"uid\":5427372,\"username\":\"李湜渰\",\"guard_level\":3,\"num\":1,\"price\":198000,\"gift_id\":10003,\"gift_name\":\"舰长\",\"start_time\":1724985039,\"end_time\":1724985039}}");
|
||||||
|
WSGuardBuy wsguardBuy = new WSGuardBuy(json);
|
||||||
|
System.out.println(wsguardBuy);
|
||||||
|
}
|
||||||
|
public WSGuardBuy(JSONObject json) {
|
||||||
|
super(json);
|
||||||
|
JSONObject data = json.getJSONObject("data");
|
||||||
|
uid = data.getLong("uid");
|
||||||
|
username = data.getString("username");
|
||||||
|
guardLevel = data.getLong("guard_level");
|
||||||
|
num = data.getLong("num");
|
||||||
|
price = data.getLong("price");
|
||||||
|
giftID = data.getLong("gift_id");
|
||||||
|
giftName = data.getString("gift_name");
|
||||||
|
startTime = data.getLong("start_time");
|
||||||
|
endTime = data.getLong("end_time");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 进场信息
|
||||||
|
* <a href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/message_stream.md#%E8%BF%9B%E5%9C%BA%E6%88%96%E5%85%B3%E6%B3%A8%E6%B6%88%E6%81%AF">进场</a>
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class WSInteractWord extends WSData {
|
||||||
|
public final static int TYPE_ENTER = 1;
|
||||||
|
public final static int TYPE_FOLLOW = 2;
|
||||||
|
private int type; //1为进场,2为关注
|
||||||
|
private long roomId;
|
||||||
|
private long timer;
|
||||||
|
private WSUserMedal medal;
|
||||||
|
private long uid;
|
||||||
|
private String uname;
|
||||||
|
private String uname_color;
|
||||||
|
private String face;
|
||||||
|
|
||||||
|
|
||||||
|
public WSInteractWord(JSONObject json) {
|
||||||
|
super(json);
|
||||||
|
JSONObject data = json.getJSONObject("data");
|
||||||
|
JSONObject medalJson = data.containsKey("fans_medal") ? data.getJSONObject("fans_medal"):null;
|
||||||
|
type = data.getIntValue("msg_type");
|
||||||
|
roomId = data.getLong("roomid");
|
||||||
|
timer = data.getLong("score");
|
||||||
|
uid = data.getLong("uid");
|
||||||
|
uname = data.getString("uname");
|
||||||
|
uname_color = data.getString("uname_color");
|
||||||
|
face = data.getJSONObject("uinfo").getJSONObject("base").getString("face");
|
||||||
|
if (medalJson != null) {
|
||||||
|
medal = new WSUserMedal();
|
||||||
|
medal.setUid(medalJson.getLong("anchor_roomid"));
|
||||||
|
medal.setMedal_name(medalJson.getString("medal_name"));
|
||||||
|
medal.setMedal_color(Integer.toHexString(medalJson.getIntValue("medal_color")));
|
||||||
|
medal.setMedal_level(medalJson.getIntValue("medal_level"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUname_color() {
|
||||||
|
if (StringUtils.hasLength(uname_color)) {
|
||||||
|
uname_color = "FFFFFF";
|
||||||
|
}
|
||||||
|
return uname_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "WSInteractWord{" +
|
||||||
|
"type=" + type +
|
||||||
|
", roomId=" + roomId +
|
||||||
|
", timer=" + timer +
|
||||||
|
", medal=" + medal +
|
||||||
|
", uid=" + uid +
|
||||||
|
", uname='" + uname + '\'' +
|
||||||
|
", uname_color='" + uname_color + '\'' +
|
||||||
|
", face='" + face + '\'' +
|
||||||
|
", cmd='" + cmd + '\'' +
|
||||||
|
", jsonSrc='" + jsonSrc + '\'' +
|
||||||
|
", ws_timer=" + ws_timer +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class WSMedalInfo extends BaseBean {
|
||||||
|
@JSONField(name = "anchor_roomid")
|
||||||
|
private long anchorRoomid;
|
||||||
|
@JSONField(name = "anchor_uname")
|
||||||
|
private String anchorUname;
|
||||||
|
@JSONField(name = "guard_level")
|
||||||
|
private long guardLevel;
|
||||||
|
@JSONField(name = "icon_id")
|
||||||
|
private long iconID;
|
||||||
|
@JSONField(name = "is_lighted")
|
||||||
|
private long isLighted;
|
||||||
|
@JSONField(name = "medal_color")
|
||||||
|
private long medalColor;
|
||||||
|
@JSONField(name = "medal_color_border")
|
||||||
|
private long medalColorBorder;
|
||||||
|
@JSONField(name = "medal_color_end")
|
||||||
|
private long medalColorEnd;
|
||||||
|
@JSONField(name = "medal_color_start")
|
||||||
|
private long medalColorStart;
|
||||||
|
@JSONField(name = "medal_level")
|
||||||
|
private long medalLevel;
|
||||||
|
@JSONField(name = "medal_name")
|
||||||
|
private String medalName;
|
||||||
|
@JSONField(name = "special")
|
||||||
|
private String special;
|
||||||
|
@JSONField(name = "target_id")
|
||||||
|
private long targetID;
|
||||||
|
}
|
||||||
@@ -0,0 +1,246 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@lombok.Data
|
||||||
|
public class WSSendGift extends WSData {
|
||||||
|
private Data data;
|
||||||
|
|
||||||
|
public WSSendGift(JSONObject json) {
|
||||||
|
super(json);
|
||||||
|
data = JSONObject.parseObject(json.getJSONObject("data").toString(), Data.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "WSSendGift{" +
|
||||||
|
"data=" + data +
|
||||||
|
", cmd='" + cmd + '\'' +
|
||||||
|
", jsonSrc='" + jsonSrc + '\'' +
|
||||||
|
", ws_timer=" + ws_timer +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class Data implements Serializable {
|
||||||
|
@JSONField(name = "action")
|
||||||
|
private String action;
|
||||||
|
@JSONField(name = "batch_combo_id")
|
||||||
|
private String batchComboID;
|
||||||
|
@JSONField(name = "batch_combo_send")
|
||||||
|
private ComboSend batchComboSend;
|
||||||
|
@JSONField(name = "combo_send")
|
||||||
|
private ComboSend comboSend;
|
||||||
|
@JSONField(name = "beatId")
|
||||||
|
private String beatID;
|
||||||
|
@JSONField(name = "biz_source")
|
||||||
|
private String bizSource;
|
||||||
|
@JSONField(name = "broadcast_id")
|
||||||
|
private long broadcastID;
|
||||||
|
@JSONField(name = "coin_type")
|
||||||
|
private String coinType;
|
||||||
|
@JSONField(name = "combo_resources_id")
|
||||||
|
private long comboResourcesID;
|
||||||
|
@JSONField(name = "combo_stay_time")
|
||||||
|
private long comboStayTime;
|
||||||
|
@JSONField(name = "combo_total_coin")
|
||||||
|
private long comboTotalCoin;
|
||||||
|
@JSONField(name = "crit_prob")
|
||||||
|
private long critProb;
|
||||||
|
@JSONField(name = "demarcation")
|
||||||
|
private long demarcation;
|
||||||
|
@JSONField(name = "discount_price")
|
||||||
|
private long discountPrice;
|
||||||
|
@JSONField(name = "dmscore")
|
||||||
|
private long dmscore;
|
||||||
|
@JSONField(name = "draw")
|
||||||
|
private long draw;
|
||||||
|
@JSONField(name = "effect")
|
||||||
|
private long effect;
|
||||||
|
@JSONField(name = "effect_block")
|
||||||
|
private long effectBlock;
|
||||||
|
@JSONField(name = "face")
|
||||||
|
private String face;
|
||||||
|
@JSONField(name = "face_effect_id")
|
||||||
|
private long faceEffectID;
|
||||||
|
@JSONField(name = "face_effect_type")
|
||||||
|
private long faceEffectType;
|
||||||
|
@JSONField(name = "face_effect_v2")
|
||||||
|
private FaceEffectV2 faceEffectV2;
|
||||||
|
@JSONField(name = "float_sc_resource_id")
|
||||||
|
private long floatScResourceID;
|
||||||
|
@JSONField(name = "giftId")
|
||||||
|
private long giftID;
|
||||||
|
@JSONField(name = "giftName")
|
||||||
|
private String giftName;
|
||||||
|
@JSONField(name = "giftType")
|
||||||
|
private long giftType;
|
||||||
|
@JSONField(name = "gift_info")
|
||||||
|
private GiftInfo giftInfo;
|
||||||
|
@JSONField(name = "gift_tag")
|
||||||
|
private List<Long> giftTag;
|
||||||
|
@JSONField(name = "gold")
|
||||||
|
private long gold;
|
||||||
|
@JSONField(name = "guard_level")
|
||||||
|
private long guardLevel;
|
||||||
|
@JSONField(name = "is_first")
|
||||||
|
private boolean isFirst;
|
||||||
|
@JSONField(name = "is_join_receiver")
|
||||||
|
private boolean isJoinReceiver;
|
||||||
|
@JSONField(name = "is_naming")
|
||||||
|
private boolean isNaming;
|
||||||
|
@JSONField(name = "is_special_batch")
|
||||||
|
private long isSpecialBatch;
|
||||||
|
@JSONField(name = "magnification")
|
||||||
|
private long magnification;
|
||||||
|
@JSONField(name = "medal_info")
|
||||||
|
private WSMedalInfo medalInfo;
|
||||||
|
@JSONField(name = "name_color")
|
||||||
|
private String nameColor;
|
||||||
|
@JSONField(name = "num")
|
||||||
|
private long num;
|
||||||
|
@JSONField(name = "original_gift_name")
|
||||||
|
private String originalGiftName;
|
||||||
|
@JSONField(name = "price")
|
||||||
|
private long price;
|
||||||
|
@JSONField(name = "rcost")
|
||||||
|
private long rcost;
|
||||||
|
@JSONField(name = "receive_user_info")
|
||||||
|
private ReceiveUserInfo receiveUserInfo;
|
||||||
|
@JSONField(name = "receiver_uinfo")
|
||||||
|
private ErUinfo receiverUinfo;
|
||||||
|
@JSONField(name = "remain")
|
||||||
|
private long remain;
|
||||||
|
@JSONField(name = "rnd")
|
||||||
|
private String rnd;
|
||||||
|
@JSONField(name = "sender_uinfo")
|
||||||
|
private ErUinfo senderUinfo;
|
||||||
|
@JSONField(name = "silver")
|
||||||
|
private long silver;
|
||||||
|
@JSONField(name = "super")
|
||||||
|
private long dataSuper;
|
||||||
|
@JSONField(name = "super_batch_gift_num")
|
||||||
|
private long superBatchGiftNum;
|
||||||
|
@JSONField(name = "super_gift_num")
|
||||||
|
private long superGiftNum;
|
||||||
|
@JSONField(name = "svga_block")
|
||||||
|
private long svgaBlock;
|
||||||
|
@JSONField(name = "switch")
|
||||||
|
private boolean dataSwitch;
|
||||||
|
@JSONField(name = "tag_image")
|
||||||
|
private String tagImage;
|
||||||
|
@JSONField(name = "tid")
|
||||||
|
private String tid;
|
||||||
|
@JSONField(name = "timestamp")
|
||||||
|
private long timestamp;
|
||||||
|
@JSONField(name = "total_coin")
|
||||||
|
private long totalCoin;
|
||||||
|
@JSONField(name = "uid")
|
||||||
|
private long uid;
|
||||||
|
@JSONField(name = "uname")
|
||||||
|
private String uname;
|
||||||
|
@JSONField(name = "wealth_level")
|
||||||
|
private long wealthLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class FaceEffectV2 implements Serializable{
|
||||||
|
@JSONField(name = "id")
|
||||||
|
private long id;
|
||||||
|
@JSONField(name = "type")
|
||||||
|
private long type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class GiftInfo implements Serializable{
|
||||||
|
@JSONField(name = "effect_id")
|
||||||
|
private long effectID;
|
||||||
|
@JSONField(name = "has_imaged_gift")
|
||||||
|
private long hasImagedGift;
|
||||||
|
@JSONField(name = "img_basic")
|
||||||
|
private String imgBasic;
|
||||||
|
@JSONField(name = "webp")
|
||||||
|
private String webp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class ReceiveUserInfo implements Serializable {
|
||||||
|
@JSONField(name = "uid")
|
||||||
|
private long uid;
|
||||||
|
@JSONField(name = "uname")
|
||||||
|
private String uname;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class ErUinfo implements Serializable {
|
||||||
|
@JSONField(name = "base")
|
||||||
|
private Base base;
|
||||||
|
@JSONField(name = "uid")
|
||||||
|
private long uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class Base implements Serializable {
|
||||||
|
@JSONField(name = "face")
|
||||||
|
private String face;
|
||||||
|
@JSONField(name = "is_mystery")
|
||||||
|
private boolean isMystery;
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
@JSONField(name = "name_color")
|
||||||
|
private long nameColor;
|
||||||
|
@JSONField(name = "name_color_str")
|
||||||
|
private String nameColorStr;
|
||||||
|
@JSONField(name = "official_info")
|
||||||
|
private OfficialInfo officialInfo;
|
||||||
|
@JSONField(name = "origin_info")
|
||||||
|
private Info originInfo;
|
||||||
|
@JSONField(name = "risk_ctrl_info")
|
||||||
|
private Info riskCtrlInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class OfficialInfo implements Serializable {
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
@JSONField(name = "role")
|
||||||
|
private long role;
|
||||||
|
@JSONField(name = "title")
|
||||||
|
private String title;
|
||||||
|
@JSONField(name = "type")
|
||||||
|
private long type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lombok.Data
|
||||||
|
public static class Info implements Serializable {
|
||||||
|
@JSONField(name = "face")
|
||||||
|
private String face;
|
||||||
|
@JSONField(name = "name")
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
@lombok.Data
|
||||||
|
public static class ComboSend implements Serializable {
|
||||||
|
@JSONField(name = "action")
|
||||||
|
private String action;
|
||||||
|
@JSONField(name = "combo_id")
|
||||||
|
private String comboID;
|
||||||
|
@JSONField(name = "combo_num")
|
||||||
|
private long comboNum;
|
||||||
|
@JSONField(name = "gift_id")
|
||||||
|
private long giftID;
|
||||||
|
@JSONField(name = "gift_name")
|
||||||
|
private String giftName;
|
||||||
|
@JSONField(name = "gift_num")
|
||||||
|
private long giftNum;
|
||||||
|
@JSONField(name = "uid")
|
||||||
|
private long uid;
|
||||||
|
@JSONField(name = "uname")
|
||||||
|
private String uname;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超级留言
|
||||||
|
* <a href="https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/message_stream.md#%E9%86%92%E7%9B%AE%E7%95%99%E8%A8%80">醒目留言</a>
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class WSSuperChatMessage extends WSData{
|
||||||
|
private long price;
|
||||||
|
private long rate;
|
||||||
|
private long uid;
|
||||||
|
private long start_time;
|
||||||
|
private long end_time;
|
||||||
|
private String message;
|
||||||
|
private String message_trans;
|
||||||
|
private String message_font_color;
|
||||||
|
private WSMedalInfo medal_info;
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JSONObject json=JSONObject.parseObject("{\"cmd\":\"SUPER_CHAT_MESSAGE\",\"data\":{\"background_bottom_color\":\"#2A60B2\",\"background_color\":\"#EDF5FF\",\"background_color_end\":\"#405D85\",\"background_color_start\":\"#3171D2\",\"background_icon\":\"\",\"background_image\":\"\",\"background_price_color\":\"#7497CD\",\"color_point\":0.7,\"dmscore\":616,\"end_time\":1724997230,\"gift\":{\"gift_id\":12000,\"gift_name\":\"醒目留言\",\"num\":1},\"group_medal\":{\"is_lighted\":0,\"medal_id\":0,\"name\":\"\"},\"id\":10427329,\"is_mystery\":false,\"is_ranked\":0,\"is_send_audit\":1,\"medal_info\":{\"anchor_roomid\":81004,\"anchor_uname\":\"艾尔莎_Channel\",\"guard_level\":0,\"icon_id\":0,\"is_lighted\":1,\"medal_color\":\"#1a544b\",\"medal_color_border\":1725515,\"medal_color_end\":5414290,\"medal_color_start\":1725515,\"medal_level\":21,\"medal_name\":\"艾薯条\",\"special\":\"\",\"target_id\":1521415},\"message\":\"莎莎,想安利你个植物大战僵尸的改版叫植物大战僵尸:肉鸽,具体情况私信你了,辛苦了\",\"message_font_color\":\"#A3F6FF\",\"message_trans\":\"サーシャ、あなたのPlantsvs.Zombiesの改版をPlantsvs.Zombiesと言いたい:肉鳩、具体的な状況は私的にあなたを信じて、お疲れ様でした\",\"price\":30,\"rate\":1000,\"start_time\":1724997170,\"time\":60,\"token\":\"9925C118\",\"trans_mark\":0,\"ts\":1724997170,\"uid\":100002175,\"uinfo\":{\"base\":{\"face\":\"https://i1.hdslb.com/bfs/face/b5ec3b1f7025b5546225ae0f36941d55ddef405b.jpg\",\"is_mystery\":false,\"name\":\"中吴同学\",\"name_color\":0,\"name_color_str\":\"#666666\",\"official_info\":{\"desc\":\"\",\"role\":0,\"title\":\"\",\"type\":-1},\"origin_info\":{\"face\":\"https://i1.hdslb.com/bfs/face/b5ec3b1f7025b5546225ae0f36941d55ddef405b.jpg\",\"name\":\"中吴同学\"}},\"guard\":{\"expired_str\":\"\",\"level\":0},\"medal\":{\"color\":1725515,\"color_border\":1725515,\"color_end\":5414290,\"color_start\":1725515,\"guard_icon\":\"\",\"guard_level\":0,\"honor_icon\":\"\",\"id\":0,\"is_light\":1,\"level\":21,\"name\":\"艾薯条\",\"ruid\":1521415,\"score\":50001980,\"typ\":0,\"user_receive_count\":0,\"v2_medal_color_border\":\"#5FC7F4FF\",\"v2_medal_color_end\":\"#43B3E3CC\",\"v2_medal_color_level\":\"#00308C99\",\"v2_medal_color_start\":\"#43B3E3CC\",\"v2_medal_color_text\":\"#FFFFFFFF\"},\"title\":{\"old_title_css_id\":\"\",\"title_css_id\":\"\"},\"uid\":100002175},\"user_info\":{\"face\":\"https://i1.hdslb.com/bfs/face/b5ec3b1f7025b5546225ae0f36941d55ddef405b.jpg\",\"face_frame\":\"\",\"guard_level\":0,\"is_main_vip\":1,\"is_svip\":0,\"is_vip\":0,\"level_color\":\"#5896de\",\"manager\":0,\"name_color\":\"#666666\",\"title\":\"\",\"uname\":\"中吴同学\",\"user_level\":25}},\"is_report\":true,\"msg_id\":\"19106780029655552:1000:1000\",\"p_is_ack\":true,\"p_msg_type\":1,\"send_time\":1724997170767}");
|
||||||
|
WSSuperChatMessage message=new WSSuperChatMessage(json);
|
||||||
|
System.out.println(message);
|
||||||
|
}
|
||||||
|
public WSSuperChatMessage(JSONObject json) {
|
||||||
|
super(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.yutou.bili.bean.websocket.live;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WSUserMedal {
|
||||||
|
private long uid;
|
||||||
|
private String medal_name;
|
||||||
|
private String medal_color = "FFFFFF";
|
||||||
|
private String medal_anchor;
|
||||||
|
private int medal_level;
|
||||||
|
|
||||||
|
public static WSUserMedal create(JSONArray array) {
|
||||||
|
if (array.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
WSUserMedal medal = new WSUserMedal();
|
||||||
|
medal.setUid(array.getIntValue(3));
|
||||||
|
medal.setMedal_name(array.getString(1));
|
||||||
|
medal.setMedal_anchor(array.getString(2));
|
||||||
|
medal.setMedal_level(array.getIntValue(0));
|
||||||
|
return medal;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.yutou.bili.databases;
|
||||||
|
|
||||||
|
import com.yutou.bili.bean.login.LoginCookie;
|
||||||
|
import com.yutou.databases.SQLiteManager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BiliBiliLoginDatabase extends SQLiteManager {
|
||||||
|
LoginCookie cookie;
|
||||||
|
private static BiliBiliLoginDatabase instance;
|
||||||
|
|
||||||
|
private BiliBiliLoginDatabase(Class<LoginCookie> tClass) {
|
||||||
|
try {
|
||||||
|
cookie = new LoginCookie();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BiliBiliLoginDatabase getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new BiliBiliLoginDatabase(LoginCookie.class);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BiliBiliLoginDatabase initData(LoginCookie cookie) {
|
||||||
|
this.cookie = cookie;
|
||||||
|
for (BuildSqlTable table : build.getTable()) {
|
||||||
|
cookie.setTableName(table.getName());
|
||||||
|
add(cookie);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginCookie get() {
|
||||||
|
List<LoginCookie> list = super.get(cookie.getTableName(), LoginCookie.class);
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
return list.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LoginCookie getDataBean() {
|
||||||
|
return new LoginCookie();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
23
biliapi/src/main/java/com/yutou/bili/enums/LiveProtocol.java
Normal file
23
biliapi/src/main/java/com/yutou/bili/enums/LiveProtocol.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package com.yutou.bili.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum LiveProtocol {
|
||||||
|
stream(0),
|
||||||
|
hls(1);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private LiveProtocol(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAll() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (LiveProtocol value : values()) {
|
||||||
|
sb.append(String.valueOf(value.value)).append(",");
|
||||||
|
}
|
||||||
|
return sb.substring(0, sb.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.yutou.bili.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum LiveVideoCodec {
|
||||||
|
AVC(0),
|
||||||
|
HEVC(1);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private LiveVideoCodec(int value) {
|
||||||
|
this.value=value;
|
||||||
|
}
|
||||||
|
public static String getAll() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (LiveVideoCodec value : values()) {
|
||||||
|
sb.append(String.valueOf(value.value)).append(",");
|
||||||
|
}
|
||||||
|
return sb.substring(0, sb.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.yutou.bili.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum LiveVideoDefinition {
|
||||||
|
|
||||||
|
LOW(80), // 流畅
|
||||||
|
HIGH(150), // 高清
|
||||||
|
SUPER(250), // 超清
|
||||||
|
BLU_RAY(400), // 蓝光
|
||||||
|
ORIGINAL(10000), // 原画
|
||||||
|
V4K(20000),
|
||||||
|
DOLBY(30000);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private LiveVideoDefinition(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
public static String getAll() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (LiveVideoDefinition value : values()) {
|
||||||
|
sb.append(String.valueOf(value.value)).append(",");
|
||||||
|
}
|
||||||
|
return sb.substring(0, sb.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.yutou.bili.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum LiveVideoFormat {
|
||||||
|
FLV(0),
|
||||||
|
TS(1),
|
||||||
|
FMP4(2);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private LiveVideoFormat(int value) {
|
||||||
|
this.value=value;
|
||||||
|
}
|
||||||
|
public static String getAll() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (LiveVideoFormat value : values()) {
|
||||||
|
sb.append(String.valueOf(value.value)).append(",");
|
||||||
|
}
|
||||||
|
return sb.substring(0, sb.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package com.yutou.bili.net;
|
||||||
|
|
||||||
|
import com.yutou.bili.bean.login.CheckCookieBean;
|
||||||
|
import com.yutou.bili.bean.login.LoginInfoBean;
|
||||||
|
import com.yutou.inter.IHttpApiCheckCallback;
|
||||||
|
import com.yutou.okhttp.HttpCallback;
|
||||||
|
import com.yutou.utils.RSAUtils;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.OAEPParameterSpec;
|
||||||
|
import javax.crypto.spec.PSource;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class BiliCookieManager {
|
||||||
|
public static final int COOKIE_INVALID = -101;
|
||||||
|
public static final int COOKIE_SUCCESS = 0;
|
||||||
|
|
||||||
|
private static final String PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
|
||||||
|
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg\n" +
|
||||||
|
"Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71\n" +
|
||||||
|
"nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40\n" +
|
||||||
|
"JNrRuoEUXpabUzGB8QIDAQAB\n" +
|
||||||
|
"-----END PUBLIC KEY-----";
|
||||||
|
|
||||||
|
public void checkCookie(IHttpApiCheckCallback<Integer> callback){
|
||||||
|
BiliLoginNetApiManager.getInstance().getLoginApi(true)
|
||||||
|
.checkCookie().enqueue(new HttpCallback<CheckCookieBean>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, CheckCookieBean response, String rawResponse) {
|
||||||
|
if(code==-101){
|
||||||
|
// TODO cookie失效,需要重新登录
|
||||||
|
callback.onError(COOKIE_INVALID,"cookie失效,需要重新登录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(response.isRefresh()){
|
||||||
|
refreshCookie();
|
||||||
|
}
|
||||||
|
callback.onSuccess(COOKIE_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <a href="https://socialsisteryi.github.io/bilibili-API-collect/docs/login/cookie_refresh.html#java">文档地址</a>
|
||||||
|
*/
|
||||||
|
private void refreshCookie(){
|
||||||
|
try {
|
||||||
|
String refreshTime = String.format("refresh_%d", System.currentTimeMillis());
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
String publicKeyStr = PUBLIC_KEY
|
||||||
|
.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||||
|
.replace("-----END PUBLIC KEY-----", "")
|
||||||
|
.replace("\n", "")
|
||||||
|
.trim();
|
||||||
|
byte[] publicBytes = Base64.getDecoder().decode(publicKeyStr);
|
||||||
|
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes);
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
|
||||||
|
|
||||||
|
String algorithm = "RSA/ECB/OAEPPadding";
|
||||||
|
Cipher cipher = Cipher.getInstance(algorithm);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
|
||||||
|
// Encode the plaintext to bytes
|
||||||
|
byte[] plaintextBytes = refreshTime.getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
// Add OAEP padding to the plaintext bytes
|
||||||
|
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParams);
|
||||||
|
// Encrypt the padded plaintext bytes
|
||||||
|
byte[] encryptedBytes = cipher.doFinal(plaintextBytes);
|
||||||
|
// Convert the encrypted bytes to a Base64-encoded string
|
||||||
|
String encrypted = new BigInteger(1, encryptedBytes).toString(16);
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.yutou.bili.net;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.bili.api.LiveApi;
|
||||||
|
import com.yutou.bili.bean.login.LoginCookie;
|
||||||
|
import com.yutou.bili.databases.BiliBiliLoginDatabase;
|
||||||
|
import com.yutou.inter.IHttpApiCheckCallback;
|
||||||
|
import com.yutou.okhttp.api.BaseApi;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class BiliLiveNetApiManager extends BaseApi {
|
||||||
|
private static BiliLiveNetApiManager instance;
|
||||||
|
|
||||||
|
public static BiliLiveNetApiManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new BiliLiveNetApiManager("https://api.live.bilibili.com");
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BiliLiveNetApiManager(String URL) {
|
||||||
|
super(URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getApi(IHttpApiCheckCallback<LiveApi> callback) {
|
||||||
|
LoginCookie cookie = BiliBiliLoginDatabase.getInstance().get();
|
||||||
|
if (cookie != null) {
|
||||||
|
useCookie(JSONObject.parseObject(JSONObject.toJSONString(cookie)));
|
||||||
|
}
|
||||||
|
HashMap<String,String> header=new HashMap<>();
|
||||||
|
header.put("Accept-Language", "zh-CN,zh;q=0.8");
|
||||||
|
header.put("Referer", "https://live.bilibili.com");
|
||||||
|
header.put("Connection", "keep-alive");
|
||||||
|
header.put("Upgrade-Insecure-Requests", "1");
|
||||||
|
addHeader(header);
|
||||||
|
callback.onSuccess(createApi(LiveApi.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package com.yutou.bili.net;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.bili.api.LoginApi;
|
||||||
|
import com.yutou.bili.bean.login.LoginCookie;
|
||||||
|
import com.yutou.bili.bean.login.LoginInfoBean;
|
||||||
|
import com.yutou.bili.bean.login.QRCodeGenerateBean;
|
||||||
|
import com.yutou.bili.databases.BiliBiliLoginDatabase;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import com.yutou.okhttp.HttpCallback;
|
||||||
|
import com.yutou.okhttp.api.BaseApi;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.ParsePosition;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class BiliLoginNetApiManager extends BaseApi {
|
||||||
|
public static final int LOGIN_QRCODE = 100;
|
||||||
|
public static final int LOGIN_SUCCESS = 101;
|
||||||
|
|
||||||
|
private static BiliLoginNetApiManager instance;
|
||||||
|
LoginApi loginApi;
|
||||||
|
|
||||||
|
private BiliLoginNetApiManager() {
|
||||||
|
super("https://passport.bilibili.com");
|
||||||
|
loginApi = createApi(LoginApi.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BiliLoginNetApiManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new BiliLoginNetApiManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginApi getLoginApi() {
|
||||||
|
return getLoginApi(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoginApi getLoginApi(boolean isCookie) {
|
||||||
|
if (isCookie) {
|
||||||
|
LoginCookie cookie = BiliBiliLoginDatabase.getInstance().get();
|
||||||
|
if (cookie != null) {
|
||||||
|
useCookie(JSONObject.parseObject(JSONObject.toJSONString(cookie)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return loginApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void login(HttpCallback<LoginCookie> callback) {
|
||||||
|
LoginCookie cookie = BiliBiliLoginDatabase.getInstance().get();
|
||||||
|
if (cookie != null) {
|
||||||
|
callback.onResponse(null, LOGIN_SUCCESS, null, cookie, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loginApi.getQRCodeGenerate().enqueue(new HttpCallback<QRCodeGenerateBean>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, QRCodeGenerateBean response, String rawResponse) {
|
||||||
|
String oauthKey = response.getQrcode_key();
|
||||||
|
String url = response.getUrl();
|
||||||
|
String bd = "gourl=https%3A%2F%2Fpassport.bilibili.com%2Fajax%2FminiLogin%2Fredirect&oauthKey=" + oauthKey;
|
||||||
|
callback.onResponse(headers, LOGIN_QRCODE, null, null, url);
|
||||||
|
new Thread(() -> waitLogin(oauthKey, callback)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitLogin(String oauthKey, HttpCallback<LoginCookie> callback) {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
new Timer().schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String bd = "gourl=https%3A%2F%2Fpassport.bilibili.com%2Fajax%2FminiLogin%2Fredirect&oauthKey=" + oauthKey;
|
||||||
|
if ((System.currentTimeMillis() - time) > 5 * 60 * 1000) {
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Response<HttpBody<LoginInfoBean>> response = loginApi.loginQRCode(oauthKey).execute();
|
||||||
|
Headers headers = response.headers();
|
||||||
|
HttpBody<LoginInfoBean> httpBody = response.body();
|
||||||
|
if (httpBody.getData().getCode() == 0) {
|
||||||
|
JSONObject ck = new JSONObject();
|
||||||
|
List<String> list = headers.values("set-cookie");
|
||||||
|
for (String cookie : list) {
|
||||||
|
String[] split = cookie.split(";");
|
||||||
|
for (String string : split) {
|
||||||
|
if (!ck.containsKey(string) && !StringUtils.isEmpty(string) && string.contains("=")) {
|
||||||
|
String key = string.split("=")[0].trim();
|
||||||
|
String value = string.split("=")[1].trim();
|
||||||
|
if (key.contains("Expires")) {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMMM yyyy HH:mm:ss z", Locale.ENGLISH);
|
||||||
|
sdf.setTimeZone(TimeZone.getDefault());
|
||||||
|
Date date = sdf.parse(value, new ParsePosition(0));
|
||||||
|
value = String.valueOf(date.getTime() / 1000);
|
||||||
|
}
|
||||||
|
ck.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!list.isEmpty()) {
|
||||||
|
ck.put("gourl", bd);
|
||||||
|
LoginCookie cookie = JSONObject.parseObject(ck.toString(), LoginCookie.class);
|
||||||
|
cancel();
|
||||||
|
callback.onResponse(headers, LOGIN_SUCCESS, "ok", cookie, ck.toString());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
callback.onFailure(new RuntimeException("cookie为空"));
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
cancel();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}, 1000, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.yutou.bili.net;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.bili.api.UserApi;
|
||||||
|
import com.yutou.bili.bean.login.LoginCookie;
|
||||||
|
import com.yutou.bili.databases.BiliBiliLoginDatabase;
|
||||||
|
import com.yutou.inter.IHttpApiCheckCallback;
|
||||||
|
import com.yutou.okhttp.api.BaseApi;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BiliUserNetApiManager extends BaseApi {
|
||||||
|
public static final int LOGIN_LOGOUT = 1;
|
||||||
|
|
||||||
|
public static BiliUserNetApiManager manager;
|
||||||
|
|
||||||
|
private BiliUserNetApiManager() {
|
||||||
|
super("https://api.bilibili.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BiliUserNetApiManager getInstance() {
|
||||||
|
if (manager == null) {
|
||||||
|
manager = new BiliUserNetApiManager();
|
||||||
|
}
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getUserApi(IHttpApiCheckCallback<UserApi> callback) {
|
||||||
|
LoginCookie cookie = BiliBiliLoginDatabase.getInstance().get();
|
||||||
|
if (cookie != null) {
|
||||||
|
HashMap<String, String> headers = new HashMap<>();
|
||||||
|
JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(cookie));
|
||||||
|
StringBuilder ck = new StringBuilder();
|
||||||
|
for (String key : json.keySet()) {
|
||||||
|
ck.append(key).append("=").append(json.getString(key)).append("; ");
|
||||||
|
}
|
||||||
|
headers.put("Cookie", ck.toString());
|
||||||
|
setHeaders(headers);
|
||||||
|
callback.onSuccess(createApi(UserApi.class));
|
||||||
|
} else {
|
||||||
|
callback.onError(LOGIN_LOGOUT, "未登录");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
248
biliapi/src/main/java/com/yutou/bili/net/WebSocketManager.java
Normal file
248
biliapi/src/main/java/com/yutou/bili/net/WebSocketManager.java
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
package com.yutou.bili.net;
|
||||||
|
|
||||||
|
import com.aayushatharva.brotli4j.Brotli4jLoader;
|
||||||
|
import com.aayushatharva.brotli4j.decoder.Decoder;
|
||||||
|
import com.aayushatharva.brotli4j.decoder.DecoderJNI;
|
||||||
|
import com.aayushatharva.brotli4j.decoder.DirectDecompress;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.bili.api.LiveApi;
|
||||||
|
import com.yutou.bili.bean.live.LiveDanmuInfo;
|
||||||
|
import com.yutou.bili.bean.live.LiveRoomConfig;
|
||||||
|
import com.yutou.bili.bean.websocket.WebSocketBody;
|
||||||
|
import com.yutou.bili.bean.websocket.WebSocketHeader;
|
||||||
|
import com.yutou.bili.bean.websocket.live.WSData;
|
||||||
|
import com.yutou.bili.databases.BiliBiliLoginDatabase;
|
||||||
|
import com.yutou.bili.utils.BiliUserUtils;
|
||||||
|
import com.yutou.bili.utils.BytesUtils;
|
||||||
|
import com.yutou.inter.IHttpApiCheckCallback;
|
||||||
|
import com.yutou.okhttp.HttpCallback;
|
||||||
|
import com.yutou.utils.Log;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
public class WebSocketManager {
|
||||||
|
private static WebSocketManager instance;
|
||||||
|
Map<LiveRoomConfig, WebSocketClientTh> roomMap;
|
||||||
|
|
||||||
|
private WebSocketManager() {
|
||||||
|
roomMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebSocketManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new WebSocketManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRoom(LiveRoomConfig roomConfig) {
|
||||||
|
BiliLiveNetApiManager.getInstance().getApi(new IHttpApiCheckCallback<LiveApi>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(LiveApi api) {
|
||||||
|
api.getLiveRoomDanmuInfo(roomConfig.getRoomId()).enqueue(new HttpCallback<LiveDanmuInfo>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, LiveDanmuInfo response, String rawResponse) {
|
||||||
|
if (!response.getHostList().isEmpty()) {
|
||||||
|
LiveDanmuInfo.Host host = response.getHostList().get(0);
|
||||||
|
String url = "wss://" + host.getHost() + ":" + host.getWssPort() + "/sub";
|
||||||
|
// url="ws://127.0.0.1:8765";
|
||||||
|
try {
|
||||||
|
roomConfig.setLiveInfo(response);
|
||||||
|
new WebSocketClientTh(new URI(url), roomConfig);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
throwable.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int code, String error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WebSocketClientTh extends WebSocketClient {
|
||||||
|
private LiveRoomConfig roomConfig;
|
||||||
|
private HeartbeatTask heartbeatTask;
|
||||||
|
|
||||||
|
|
||||||
|
public WebSocketClientTh(URI serverUri, LiveRoomConfig roomId) {
|
||||||
|
super(serverUri);
|
||||||
|
this.roomConfig = roomId;
|
||||||
|
heartbeatTask = new HeartbeatTask();
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen(ServerHandshake serverHandshake) {
|
||||||
|
WebSocketManager.getInstance().roomMap.put(roomConfig, this);
|
||||||
|
heartbeatTask.setSocket(this);
|
||||||
|
heartbeatTask.sendInitAuthData();
|
||||||
|
new Timer().schedule(heartbeatTask, 1000, 30000);
|
||||||
|
System.out.println("WebSocketClientTh.onOpen");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(String s) {
|
||||||
|
System.out.println("s = " + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(ByteBuffer bytes) {
|
||||||
|
System.out.println("WebSocketClientTh.onMessage");
|
||||||
|
super.onMessage(bytes);
|
||||||
|
decompress(bytes.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose(int i, String s, boolean b) {
|
||||||
|
System.out.println("WebSocketClientTh.onClose");
|
||||||
|
System.out.println("i = " + i + ", s = " + s + ", b = " + b);
|
||||||
|
WebSocketManager.getInstance().roomMap.remove(roomConfig);
|
||||||
|
heartbeatTask.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception e) {
|
||||||
|
System.out.println("WebSocketClientTh.onError");
|
||||||
|
e.printStackTrace();
|
||||||
|
WebSocketManager.getInstance().roomMap.remove(roomConfig);
|
||||||
|
heartbeatTask.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解压缩
|
||||||
|
*
|
||||||
|
* @param data 待压缩的数据
|
||||||
|
*/
|
||||||
|
public void decompress(byte[] data) {
|
||||||
|
byte[] bytes = new byte[data.length - 16];
|
||||||
|
WebSocketHeader header = new WebSocketHeader(data);
|
||||||
|
System.arraycopy(data, header.getHeaderSize(), bytes, 0, data.length - header.getHeaderSize());
|
||||||
|
System.out.println("数据大小:" + header.getDataSize() + " 协议:" + header.getAgree() + " 头部大小:" + header.getHeaderSize() + " 命令:" + header.getCmdData());
|
||||||
|
switch (header.getAgree()) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
danmu(bytes);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unzipDanmu(bytes, header.getAgree() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void danmu(byte[] bytes) {
|
||||||
|
Log.i("未压缩:" + new String(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unzipDanmu(byte[] bytes, boolean useHeader) {
|
||||||
|
try {
|
||||||
|
Brotli4jLoader.ensureAvailability();
|
||||||
|
DirectDecompress directDecompress = Decoder.decompress(bytes);
|
||||||
|
if (directDecompress.getResultStatus() == DecoderJNI.Status.DONE) {
|
||||||
|
WebSocketBody body = new WebSocketBody(directDecompress.getDecompressedData());
|
||||||
|
Log.i("3协议:" + useHeader + " 命令数:" + body.getBodyList().size());
|
||||||
|
for (JSONObject json : body.getBodyList()) {
|
||||||
|
Log.i("解压:" + WSData.parse(json));
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
System.out.println();
|
||||||
|
} else {
|
||||||
|
Log.e(new RuntimeException("解压失败"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HeartbeatTask extends TimerTask {
|
||||||
|
WebSocketClientTh socket;
|
||||||
|
|
||||||
|
public void setSocket(WebSocketClientTh socket) {
|
||||||
|
this.socket = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
// com.yutou.bilibili.Tools.Log.i("-------发送心跳--------");
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
outputStream.write(BytesUtils.toLH("[object Object]".length() + 16));
|
||||||
|
outputStream.write(new byte[]{0, 16, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1});
|
||||||
|
outputStream.write("[object Object]".getBytes(StandardCharsets.UTF_8));
|
||||||
|
outputStream.flush();
|
||||||
|
socket.send(outputStream.toByteArray());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendInitAuthData() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
if (roomConfig.isLogin()) {
|
||||||
|
json.put("uid", Long.parseLong(roomConfig.getUid()));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
json.put("uid", 0);
|
||||||
|
}
|
||||||
|
BiliUserUtils.getBuvid(new IHttpApiCheckCallback<String>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String api) {
|
||||||
|
try {
|
||||||
|
json.put("roomid", Long.parseLong(roomConfig.getRoomId()));
|
||||||
|
json.put("protover", 3);
|
||||||
|
json.put("buvid", api);
|
||||||
|
json.put("platform", "web");
|
||||||
|
json.put("type", 2);
|
||||||
|
json.put("key", roomConfig.getLiveInfo().getToken());
|
||||||
|
byte[] bytes = {0, 16, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1};
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
System.out.println("bytes.length = " + bytes.length);
|
||||||
|
Log.i(json);
|
||||||
|
outputStream.write(BytesUtils.toLH(json.toString().length() + 16));
|
||||||
|
outputStream.write(bytes);
|
||||||
|
outputStream.write(json.toJSONString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
outputStream.flush();
|
||||||
|
BytesUtils.printHex(outputStream.toByteArray());
|
||||||
|
System.out.println(socket.isOpen());
|
||||||
|
socket.send(outputStream.toByteArray());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int code, String error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.yutou.bili.utils;
|
||||||
|
|
||||||
|
import com.yutou.bili.api.UserApi;
|
||||||
|
import com.yutou.bili.bean.live.SpiBean;
|
||||||
|
import com.yutou.bili.net.BiliUserNetApiManager;
|
||||||
|
import com.yutou.inter.IHttpApiCheckCallback;
|
||||||
|
import com.yutou.okhttp.HttpCallback;
|
||||||
|
import com.yutou.utils.RedisTools;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
|
||||||
|
public class BiliUserUtils {
|
||||||
|
public static void getBuvid(IHttpApiCheckCallback<String> callback) {
|
||||||
|
String buvid= RedisTools.get(RedisTools.BILI_USER_BUVID);
|
||||||
|
if(buvid!=null){
|
||||||
|
callback.onSuccess(buvid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BiliUserNetApiManager.getInstance().getUserApi(new IHttpApiCheckCallback<UserApi>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(UserApi api) {
|
||||||
|
api.getFingerSpi().enqueue(new HttpCallback<SpiBean>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, SpiBean response, String rawResponse) {
|
||||||
|
RedisTools.set(RedisTools.BILI_USER_BUVID,response.getB_3());
|
||||||
|
callback.onSuccess(response.getB_3());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int code, String error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
41
biliapi/src/main/java/com/yutou/bili/utils/BytesUtils.java
Normal file
41
biliapi/src/main/java/com/yutou/bili/utils/BytesUtils.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package com.yutou.bili.utils;
|
||||||
|
|
||||||
|
import com.yutou.utils.Log;
|
||||||
|
import jakarta.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
|
public class BytesUtils {
|
||||||
|
|
||||||
|
public static int bytesToInt2(byte[] src, int offset) {
|
||||||
|
int value;
|
||||||
|
value = (int) (((src[offset] & 0xFF) << 24)
|
||||||
|
| ((src[offset + 1] & 0xFF) << 16)
|
||||||
|
| ((src[offset + 2] & 0xFF) << 8)
|
||||||
|
| (src[offset + 3] & 0xFF));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void printHex(byte[] byteArray) {
|
||||||
|
System.out.println("\n\n\n");
|
||||||
|
String str = DatatypeConverter.printHexBinary(byteArray);
|
||||||
|
Log.i(str);
|
||||||
|
for (int i = 0; i < str.length(); i = i + 4) {
|
||||||
|
if (i % 32 == 0 && i != 0) {
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
if (str.length() - i > 4) {
|
||||||
|
System.out.print(str.substring(i, i + 4) + " ");
|
||||||
|
} else {
|
||||||
|
System.out.println(str.substring(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("\n\n\n");
|
||||||
|
}
|
||||||
|
public static byte[] toLH(int n) {
|
||||||
|
byte[] b = new byte[4];
|
||||||
|
b[3] = (byte) (n & 0xff);
|
||||||
|
b[2] = (byte) (n >> 8 & 0xff);
|
||||||
|
b[1] = (byte) (n >> 16 & 0xff);
|
||||||
|
b[0] = (byte) (n >> 24 & 0xff);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.yutou.bili.utils;
|
||||||
|
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class LiveHeartBeat {
|
||||||
|
private static LiveHeartBeat instance;
|
||||||
|
private HeartBeatThread thread;
|
||||||
|
Map<String,HeartBeatThread> heartBeatMap=new HashMap<>();
|
||||||
|
|
||||||
|
public static LiveHeartBeat getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new LiveHeartBeat();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LiveHeartBeat() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHeartBeat(String roomId) {
|
||||||
|
if(heartBeatMap.containsKey(roomId)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeHeartBeat(String roomId) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endAllHeartBeat() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HeartBeatThread extends WebSocketClient {
|
||||||
|
|
||||||
|
|
||||||
|
public HeartBeatThread(URI serverUri) {
|
||||||
|
super(serverUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen(ServerHandshake serverHandshake) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(String s) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose(int i, String s, boolean b) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
34
common/pom.xml
Normal file
34
common/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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.yutou</groupId>
|
||||||
|
<artifactId>bilibili</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.12.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.retrofit2</groupId>
|
||||||
|
<artifactId>retrofit</artifactId>
|
||||||
|
<version>2.11.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.yutou.databases;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AbsDatabasesBean {
|
||||||
|
String tableName;
|
||||||
|
|
||||||
|
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(this, JSONWriter.Feature.WriteMapNullValue));
|
||||||
|
json.remove("tableName");
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
302
common/src/main/java/com/yutou/databases/SQLiteManager.java
Normal file
302
common/src/main/java/com/yutou/databases/SQLiteManager.java
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
package com.yutou.databases;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.utils.Log;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class SQLiteManager {
|
||||||
|
protected Connection conn;
|
||||||
|
private String url = "jdbc:sqlite:";
|
||||||
|
private File sql;
|
||||||
|
@Getter
|
||||||
|
public BuildSql build;
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
AbsDatabasesBean data = getDataBean();
|
||||||
|
List<BuildSqlItem> items = new ArrayList<>();
|
||||||
|
Field[] fields = data.getClass().getDeclaredFields();
|
||||||
|
for (Field field : fields) {
|
||||||
|
String name = field.getAnnotation(JSONField.class).name();
|
||||||
|
if (name.equals("tableName")) continue;
|
||||||
|
String type = BuildSqlItem.TYPE_STRING;
|
||||||
|
if (field.getType() == int.class) {
|
||||||
|
type = BuildSqlItem.TYPE_INT;
|
||||||
|
} else if (field.getType() == String.class) {
|
||||||
|
type = BuildSqlItem.TYPE_STRING;
|
||||||
|
} else if (field.getType() == Date.class) {
|
||||||
|
type = BuildSqlItem.TYPE_TIME;
|
||||||
|
}
|
||||||
|
items.add(BuildSqlItem.create().setName(name).setType(type).setNull(true).setKey(false));
|
||||||
|
}
|
||||||
|
BuildSql sql = BuildSql.create()
|
||||||
|
.setFileName("bilibili_login.db")
|
||||||
|
.setTable(BuildSqlTable.create().setName(data.getTableName()).setItem(items));
|
||||||
|
build(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void startBatch() {
|
||||||
|
try {
|
||||||
|
conn.setAutoCommit(false);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeBatch() {
|
||||||
|
try {
|
||||||
|
conn.setAutoCommit(true);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
try {
|
||||||
|
conn.close();
|
||||||
|
} catch (SQLException throwables) {
|
||||||
|
throwables.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commit() {
|
||||||
|
try {
|
||||||
|
conn.commit();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends AbsDatabasesBean> void add(T t) {
|
||||||
|
try {
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StringBuilder value = new StringBuilder();
|
||||||
|
sb.append("INSERT INTO `").append(t.getTableName()).append("` ");
|
||||||
|
sb.append("(");
|
||||||
|
value.append("(");
|
||||||
|
for (String key : t.toJson().keySet()) {
|
||||||
|
sb.append("`").append(key).append("`,");
|
||||||
|
value.append("'").append(t.toJson().get(key)).append("',");
|
||||||
|
}
|
||||||
|
sb.deleteCharAt(sb.length() - 1);
|
||||||
|
value.deleteCharAt(value.length() - 1);
|
||||||
|
value.append(")");
|
||||||
|
sb.append(") VALUES ");
|
||||||
|
sb.append(value);
|
||||||
|
statement.executeUpdate(sb.toString());
|
||||||
|
statement.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends AbsDatabasesBean> List<T> get(String table, Class<T> tClass) {
|
||||||
|
List<T> list = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
String sql = "SELECT * FROM `" + table + "`";
|
||||||
|
ResultSet resultSet = statement.executeQuery(sql);
|
||||||
|
while (resultSet.next()) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
|
||||||
|
String name = resultSet.getMetaData().getColumnName(i + 1);
|
||||||
|
json.put(name, resultSet.getObject(name));
|
||||||
|
}
|
||||||
|
list.add(json.to(tClass));
|
||||||
|
}
|
||||||
|
resultSet.close();
|
||||||
|
statement.closeOnCompletion();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createSql(BuildSql build) {
|
||||||
|
try {
|
||||||
|
sql.mkdirs();
|
||||||
|
sql.delete();
|
||||||
|
conn = DriverManager.getConnection(url + sql.getAbsolutePath());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
startBatch();
|
||||||
|
for (BuildSqlTable table : build.getTable()) {
|
||||||
|
Log.i("创建表:" + table.getName());
|
||||||
|
createSqlOfTable(table);
|
||||||
|
}
|
||||||
|
closeBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSqlOfTable(BuildSqlTable table) {
|
||||||
|
String tableName = table.getName();
|
||||||
|
try {
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
List<BuildSqlItem> items = table.getItem();
|
||||||
|
StringBuilder sql = new StringBuilder();
|
||||||
|
sql.append("CREATE TABLE `")
|
||||||
|
.append(tableName)
|
||||||
|
.append("` (");
|
||||||
|
for (BuildSqlItem item : items) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
String type = switch (item.getType()) {
|
||||||
|
case "int" -> " INTEGER ";
|
||||||
|
case "TIME" -> " NUMERIC ";
|
||||||
|
default -> " TEXT ";
|
||||||
|
};
|
||||||
|
builder.append("`")
|
||||||
|
.append(item.getName())
|
||||||
|
.append("`")
|
||||||
|
.append(type)
|
||||||
|
.append(item.isNull() ? "" : " NOT NULL ")
|
||||||
|
.append(item.isKey() ? " PRIMARY KEY AUTOINCREMENT " : "")
|
||||||
|
.append(",");
|
||||||
|
sql.append(builder.toString());
|
||||||
|
}
|
||||||
|
sql.append(");");
|
||||||
|
System.out.println("创建表 > " + sql.toString());
|
||||||
|
statement.execute(sql.toString().replace(",);", ");"));
|
||||||
|
statement.closeOnCompletion();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(BuildSql buildSql) {
|
||||||
|
try {
|
||||||
|
this.build = buildSql;
|
||||||
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
sql = new File("databases" + File.separator + buildSql.getFileName());
|
||||||
|
if (!sql.exists()) {
|
||||||
|
createSql(buildSql);
|
||||||
|
} else {
|
||||||
|
conn = DriverManager.getConnection(url + sql.getAbsolutePath());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setDB(String fileName) {
|
||||||
|
try {
|
||||||
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
sql = new File("db" + File.separator + fileName);
|
||||||
|
if (sql.exists()) {
|
||||||
|
if (conn != null && !conn.isClosed()) {
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
conn = DriverManager.getConnection(url + sql.getAbsolutePath());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract AbsDatabasesBean getDataBean();
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class BuildSql {
|
||||||
|
String fileName;
|
||||||
|
List<BuildSqlTable> table;
|
||||||
|
|
||||||
|
public static BuildSql create() {
|
||||||
|
return new BuildSql();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSql setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSql setTable(List<BuildSqlTable> table) {
|
||||||
|
this.table = table;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSql setTable(BuildSqlTable... table) {
|
||||||
|
this.table = List.of(table);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class BuildSqlTable {
|
||||||
|
String name;
|
||||||
|
List<BuildSqlItem> item;
|
||||||
|
|
||||||
|
public static BuildSqlTable create() {
|
||||||
|
return new BuildSqlTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSqlTable setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSqlTable setItem(List<BuildSqlItem> item) {
|
||||||
|
this.item = item;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSqlTable setItem(BuildSqlItem... item) {
|
||||||
|
this.item = List.of(item);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class BuildSqlItem {
|
||||||
|
public static final String TYPE_INT = "init";
|
||||||
|
public static final String TYPE_STRING = "String";
|
||||||
|
public static final String TYPE_TIME = "TIME";
|
||||||
|
|
||||||
|
|
||||||
|
String name;
|
||||||
|
String type;
|
||||||
|
boolean isNull;
|
||||||
|
boolean isKey;
|
||||||
|
|
||||||
|
public static BuildSqlItem create() {
|
||||||
|
return new BuildSqlItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSqlItem setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSqlItem setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSqlItem setNull(boolean aNull) {
|
||||||
|
isNull = aNull;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildSqlItem setKey(boolean key) {
|
||||||
|
isKey = key;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.yutou.inter;
|
||||||
|
|
||||||
|
public interface IHttpApiCheckCallback<T> {
|
||||||
|
void onSuccess(T api);
|
||||||
|
|
||||||
|
void onError(int code, String error);
|
||||||
|
}
|
||||||
6
common/src/main/java/com/yutou/okhttp/BaseBean.java
Normal file
6
common/src/main/java/com/yutou/okhttp/BaseBean.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class BaseBean implements Serializable {
|
||||||
|
}
|
||||||
11
common/src/main/java/com/yutou/okhttp/FileBody.java
Normal file
11
common/src/main/java/com/yutou/okhttp/FileBody.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FileBody<T> {
|
||||||
|
InputStream inputStream;
|
||||||
|
T t;
|
||||||
|
}
|
||||||
103
common/src/main/java/com/yutou/okhttp/FileCallback.java
Normal file
103
common/src/main/java/com/yutou/okhttp/FileCallback.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public abstract class FileCallback<T> implements Callback<FileBody<T>> {
|
||||||
|
|
||||||
|
private static ThreadPoolExecutor executor;
|
||||||
|
private final T bean;
|
||||||
|
|
||||||
|
|
||||||
|
public FileCallback(T bean) {
|
||||||
|
this.bean = bean;
|
||||||
|
if (executor == null) {
|
||||||
|
executor = new ThreadPoolExecutor(2, 4, Long.MAX_VALUE, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DownloadTask implements Runnable {
|
||||||
|
private T bean;
|
||||||
|
private Headers headers;
|
||||||
|
private HttpUrl url;
|
||||||
|
private InputStream inputStream;
|
||||||
|
|
||||||
|
public DownloadTask(T bean, Headers headers, HttpUrl url, InputStream inputStream) {
|
||||||
|
this.bean = bean;
|
||||||
|
|
||||||
|
this.headers = headers;
|
||||||
|
this.url = url;
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
System.out.println("开始下载");
|
||||||
|
File file = new File("download" + File.separator + System.currentTimeMillis() + ".flv");
|
||||||
|
onStart(bean);
|
||||||
|
if (!file.exists()) {
|
||||||
|
boolean mkdirs = file.getParentFile().mkdirs();
|
||||||
|
System.out.println("mkdirs = " + mkdirs);
|
||||||
|
}
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(file);
|
||||||
|
int len;
|
||||||
|
long total = 0;
|
||||||
|
byte[] bytes = new byte[4096];
|
||||||
|
boolean isDownload = true;
|
||||||
|
long available = inputStream.available();
|
||||||
|
while ((len = inputStream.read(bytes)) != -1 && isDownload) {
|
||||||
|
total += len;
|
||||||
|
outputStream.write(bytes, 0, len);
|
||||||
|
outputStream.flush();
|
||||||
|
isDownload = onDownload(headers, bean, total, available);
|
||||||
|
}
|
||||||
|
System.out.println("下载完成");
|
||||||
|
outputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
onFinish(bean);
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void onStart(T bean);
|
||||||
|
|
||||||
|
public abstract boolean onDownload(Headers headers, T bean, long len, long total);
|
||||||
|
|
||||||
|
public abstract void onFinish(T bean);
|
||||||
|
|
||||||
|
public abstract void onFailure(T bean, Throwable throwable);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<FileBody<T>> call, Response<FileBody<T>> response) {
|
||||||
|
executor.execute(new DownloadTask(bean, response.headers(), call.request().url(), response.body().getInputStream()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<FileBody<T>> call, Throwable throwable) {
|
||||||
|
onFailure(bean, throwable);
|
||||||
|
call.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
common/src/main/java/com/yutou/okhttp/GetRequestParams.java
Normal file
32
common/src/main/java/com/yutou/okhttp/GetRequestParams.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class GetRequestParams implements IRequestParam {
|
||||||
|
/**
|
||||||
|
* 构建Request
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Request getRequest(HashMap<String, String> headerMap, HashMap<String, String> map, Request request) {
|
||||||
|
Headers.Builder headerBuild = request.headers().newBuilder();
|
||||||
|
if (!headerMap.isEmpty()) {
|
||||||
|
for (String key : headerMap.keySet()) {
|
||||||
|
headerBuild.add(key, headerMap.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//添加公共参数
|
||||||
|
HttpUrl.Builder builder = request.url().newBuilder();
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
builder.addQueryParameter(key, String.valueOf(map.get(key)));
|
||||||
|
}
|
||||||
|
return request.newBuilder().url(builder.build()).headers(headerBuild.build()).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
common/src/main/java/com/yutou/okhttp/HttpBody.java
Normal file
14
common/src/main/java/com/yutou/okhttp/HttpBody.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class HttpBody<T> {
|
||||||
|
private String msg;
|
||||||
|
private String status;
|
||||||
|
private int code;
|
||||||
|
private int retcode;
|
||||||
|
private T data;
|
||||||
|
private String src;
|
||||||
|
|
||||||
|
}
|
||||||
35
common/src/main/java/com/yutou/okhttp/HttpCallback.java
Normal file
35
common/src/main/java/com/yutou/okhttp/HttpCallback.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public abstract class HttpCallback<T> implements Callback<HttpBody<T>> {
|
||||||
|
|
||||||
|
public abstract void onResponse(Headers headers,int code, String status, T response, String rawResponse);
|
||||||
|
|
||||||
|
public abstract void onFailure(Throwable throwable);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<HttpBody<T>> call, Response<HttpBody<T>> response) {
|
||||||
|
if (response.body() != null) {
|
||||||
|
onResponse(
|
||||||
|
response.headers(),
|
||||||
|
response.body().getRetcode(),
|
||||||
|
response.body().getStatus(),
|
||||||
|
response.body().getData(),
|
||||||
|
response.body().getSrc()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
onFailure(new NullPointerException("response body is null"));
|
||||||
|
}
|
||||||
|
call.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<HttpBody<T>> call, Throwable throwable) {
|
||||||
|
onFailure(throwable);
|
||||||
|
call.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
|
||||||
|
import com.yutou.utils.Log;
|
||||||
|
import okhttp3.*;
|
||||||
|
import okhttp3.internal.http.HttpHeaders;
|
||||||
|
import okio.Buffer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class HttpLoggingInterceptor implements Interceptor {
|
||||||
|
private static final String TAG = "HttpLogging";
|
||||||
|
|
||||||
|
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
private volatile Level printLevel = Level.NONE;
|
||||||
|
private java.util.logging.Level colorLevel;
|
||||||
|
private Logger logger;
|
||||||
|
|
||||||
|
private static boolean prLog;
|
||||||
|
|
||||||
|
public static void setLog(boolean log) {
|
||||||
|
prLog = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Level {
|
||||||
|
NONE, //不打印log
|
||||||
|
BASIC, //只打印 请求首行 和 响应首行
|
||||||
|
HEADERS, //打印请求和响应的所有 Header
|
||||||
|
BODY //所有数据全部打印
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpLoggingInterceptor(String tag) {
|
||||||
|
logger = Logger.getLogger(tag);
|
||||||
|
colorLevel = java.util.logging.Level.INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrintLevel(Level level) {
|
||||||
|
if (printLevel == null)
|
||||||
|
throw new NullPointerException("printLevel == null. Use Level.NONE instead.");
|
||||||
|
printLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorLevel(java.util.logging.Level level) {
|
||||||
|
colorLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log(String message) {
|
||||||
|
//logger.log(colorLevel, message);
|
||||||
|
if (prLog) {
|
||||||
|
Log.i(TAG, message);
|
||||||
|
}
|
||||||
|
//Log.e(TAG,message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response intercept(Chain chain) throws IOException {
|
||||||
|
Request request = chain.request();
|
||||||
|
if (request.body() != null && request.body().contentLength() == 0) {
|
||||||
|
request = chain.call().request();
|
||||||
|
}
|
||||||
|
if (printLevel == Level.NONE) {
|
||||||
|
return chain.proceed(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
//请求日志拦截
|
||||||
|
logForRequest(request, chain.connection());
|
||||||
|
|
||||||
|
//执行请求,计算请求时间
|
||||||
|
long startNs = System.nanoTime();
|
||||||
|
Response response;
|
||||||
|
try {
|
||||||
|
response = chain.proceed(request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log("<-- HTTP FAILED: " + e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
|
||||||
|
|
||||||
|
//响应日志拦截
|
||||||
|
return logForResponse(response, tookMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logForRequest(Request request, Connection connection) throws IOException {
|
||||||
|
boolean logBody = (printLevel == Level.BODY);
|
||||||
|
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
|
||||||
|
RequestBody requestBody = request.body();
|
||||||
|
boolean hasRequestBody = requestBody != null;
|
||||||
|
Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol;
|
||||||
|
log(requestStartMessage);
|
||||||
|
|
||||||
|
if (logHeaders) {
|
||||||
|
if (hasRequestBody) {
|
||||||
|
// Request body headers are only present when installed as a network interceptor. Force
|
||||||
|
// them to be included (when available) so there values are known.
|
||||||
|
if (requestBody.contentType() != null) {
|
||||||
|
log("\tContent-Type: " + requestBody.contentType());
|
||||||
|
}
|
||||||
|
if (requestBody.contentLength() != -1) {
|
||||||
|
log("\tContent-Length: " + requestBody.contentLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Headers headers = request.headers();
|
||||||
|
for (int i = 0, count = headers.size(); i < count; i++) {
|
||||||
|
String name = headers.name(i);
|
||||||
|
// Skip headers from the request body as they are explicitly logged above.
|
||||||
|
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
|
||||||
|
log("\t" + name + ": " + headers.value(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log(" ");
|
||||||
|
if (logBody && hasRequestBody) {
|
||||||
|
if (isPlaintext(requestBody.contentType())) {
|
||||||
|
bodyToString(request);
|
||||||
|
} else {
|
||||||
|
log("\tbody: maybe [binary body], omitted!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
log("--> END " + request.method());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response logForResponse(Response response, long tookMs) {
|
||||||
|
Response.Builder builder = response.newBuilder();
|
||||||
|
Response clone = builder.build();
|
||||||
|
ResponseBody responseBody = clone.body();
|
||||||
|
boolean logBody = (printLevel == Level.BODY);
|
||||||
|
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
|
||||||
|
|
||||||
|
try {
|
||||||
|
log("<-- " + clone.code() + ' ' + clone.message() + ' ' + clone.request().url() + " (" + tookMs + "ms)");
|
||||||
|
if (logHeaders) {
|
||||||
|
Headers headers = clone.headers();
|
||||||
|
for (int i = 0, count = headers.size(); i < count; i++) {
|
||||||
|
log("\t" + headers.name(i) + ": " + headers.value(i));
|
||||||
|
}
|
||||||
|
log(" ");
|
||||||
|
if (logBody && HttpHeaders.hasBody(clone)) {
|
||||||
|
if (responseBody == null) return response;
|
||||||
|
|
||||||
|
if (isPlaintext(responseBody.contentType())) {
|
||||||
|
byte[] bytes = responseBody.byteStream().readAllBytes();
|
||||||
|
MediaType contentType = responseBody.contentType();
|
||||||
|
String body = new String(bytes, getCharset(contentType));
|
||||||
|
log("\tbody:" + body);
|
||||||
|
responseBody = ResponseBody.create(responseBody.contentType(), bytes);
|
||||||
|
return response.newBuilder().body(responseBody).build();
|
||||||
|
} else {
|
||||||
|
log("\tbody: maybe [binary body], omitted!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
log("<-- END HTTP");
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Charset getCharset(MediaType contentType) {
|
||||||
|
Charset charset = contentType != null ? contentType.charset(UTF8) : UTF8;
|
||||||
|
if (charset == null) charset = UTF8;
|
||||||
|
return charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the body in question probably contains human readable text. Uses a small sample
|
||||||
|
* of code points to detect unicode control characters commonly used in binary file signatures.
|
||||||
|
*/
|
||||||
|
private static boolean isPlaintext(MediaType mediaType) {
|
||||||
|
if (mediaType == null) return false;
|
||||||
|
if (mediaType.type() != null && mediaType.type().equals("text")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String subtype = mediaType.subtype();
|
||||||
|
if (subtype != null) {
|
||||||
|
subtype = subtype.toLowerCase();
|
||||||
|
if (subtype.contains("x-www-form-urlencoded") || subtype.contains("json") || subtype.contains("xml") || subtype.contains("html")) //
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bodyToString(Request request) {
|
||||||
|
try {
|
||||||
|
Request copy = request.newBuilder().build();
|
||||||
|
RequestBody body = copy.body();
|
||||||
|
if (body == null) return;
|
||||||
|
Buffer buffer = new Buffer();
|
||||||
|
body.writeTo(buffer);
|
||||||
|
Charset charset = getCharset(body.contentType());
|
||||||
|
log("\tbody:" + buffer.readString(charset));
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
common/src/main/java/com/yutou/okhttp/IRequestParam.java
Normal file
9
common/src/main/java/com/yutou/okhttp/IRequestParam.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public interface IRequestParam {
|
||||||
|
Request getRequest(HashMap<String,String> header, HashMap<String,String> map, Request request);
|
||||||
|
}
|
||||||
44
common/src/main/java/com/yutou/okhttp/ParamsContext.java
Normal file
44
common/src/main/java/com/yutou/okhttp/ParamsContext.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class ParamsContext {
|
||||||
|
private IRequestParam iRequestParam;
|
||||||
|
private Request request;
|
||||||
|
private HashMap<String, String> map;
|
||||||
|
private HashMap<String, String> headerMap;
|
||||||
|
|
||||||
|
public ParamsContext(HashMap<String, String> map, Request request) {
|
||||||
|
if (map == null) {
|
||||||
|
map = new HashMap<>();
|
||||||
|
}
|
||||||
|
this.map = map;
|
||||||
|
this.request = request;
|
||||||
|
this.headerMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParamsContext(HashMap<String, String> headerMap, HashMap<String, String> map, Request request) {
|
||||||
|
if (map == null) {
|
||||||
|
map = new HashMap<>();
|
||||||
|
}
|
||||||
|
this.map = map;
|
||||||
|
this.request = request;
|
||||||
|
this.headerMap = headerMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request getInRequest() {
|
||||||
|
switch (request.method()) {
|
||||||
|
case "GET":
|
||||||
|
iRequestParam = new GetRequestParams();
|
||||||
|
break;
|
||||||
|
case "POST":
|
||||||
|
iRequestParam = new PostRequestParams();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
headerMap.remove("tableName");
|
||||||
|
headerMap.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
|
||||||
|
return iRequestParam.getRequest(headerMap, map, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
73
common/src/main/java/com/yutou/okhttp/PostRequestParams.java
Normal file
73
common/src/main/java/com/yutou/okhttp/PostRequestParams.java
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package com.yutou.okhttp;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import okhttp3.*;
|
||||||
|
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class PostRequestParams implements IRequestParam {
|
||||||
|
@Override
|
||||||
|
public Request getRequest(HashMap<String, String> headerMap, HashMap<String, String> map, Request request) {
|
||||||
|
Headers.Builder headerBuilder = request.headers().newBuilder();
|
||||||
|
if (!headerMap.isEmpty()) {
|
||||||
|
for (String key : headerMap.keySet()) {
|
||||||
|
headerBuilder.add(key, headerMap.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (request.body() instanceof FormBody) {
|
||||||
|
FormBody.Builder bodyBuilder = new FormBody.Builder();
|
||||||
|
FormBody formBody = (FormBody) request.body();
|
||||||
|
for (int i = 0; i < formBody.size(); i++) {
|
||||||
|
bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
|
||||||
|
}
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
bodyBuilder.addEncoded(key, String.valueOf(map.get(key)));
|
||||||
|
}
|
||||||
|
formBody = bodyBuilder.build();
|
||||||
|
request = request.newBuilder().headers(headerBuilder.build()).post(formBody).build();
|
||||||
|
} else if (request.body() != null) {
|
||||||
|
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), toUrlParams(map));
|
||||||
|
request = request.newBuilder()
|
||||||
|
.headers(headerBuilder.build())
|
||||||
|
.post(request.body())
|
||||||
|
.post(requestBody).build();
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toUrlParams(JSONObject json) {
|
||||||
|
StringBuilder string = new StringBuilder();
|
||||||
|
Set<String> keys = json.keySet();
|
||||||
|
for (String key : keys) {
|
||||||
|
try {
|
||||||
|
string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key), "UTF-8"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
try {
|
||||||
|
string.append("&").append(URLEncoder.encode(key, "UTF-8")).append("=");
|
||||||
|
// string += "&" + key + "=";
|
||||||
|
} catch (Exception e1) {
|
||||||
|
string.append("&").append(key).append("=");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string = new StringBuilder(string.substring(1, string.length()).replaceAll(" ", ""));
|
||||||
|
return string.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toUrlParams(Map<String, String> map) {
|
||||||
|
if (map.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
builder.append(key).append("=").append(map.get(key)).append("&");
|
||||||
|
}
|
||||||
|
return builder.substring(0, builder.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
118
common/src/main/java/com/yutou/okhttp/api/BaseApi.java
Normal file
118
common/src/main/java/com/yutou/okhttp/api/BaseApi.java
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package com.yutou.okhttp.api;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.internal.bind.DateTypeAdapter;
|
||||||
|
import com.yutou.okhttp.HttpLoggingInterceptor;
|
||||||
|
import com.yutou.okhttp.ParamsContext;
|
||||||
|
import com.yutou.okhttp.converter.JsonCallAdapter;
|
||||||
|
import com.yutou.okhttp.converter.JsonConverterFactory;
|
||||||
|
import okhttp3.*;
|
||||||
|
import retrofit2.CallAdapter;
|
||||||
|
import retrofit2.Converter;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class BaseApi {
|
||||||
|
private String URL;
|
||||||
|
private HashMap<String, String> params = new HashMap<>();
|
||||||
|
private HashMap<String, String> headers = new HashMap<>();
|
||||||
|
|
||||||
|
public BaseApi(String URL) {
|
||||||
|
this.URL = URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApi setURL(String URL) {
|
||||||
|
this.URL = URL;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApi setHeaders(HashMap<String, String> headers) {
|
||||||
|
this.headers = headers;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public void addHeader(HashMap<String,String> headers){
|
||||||
|
this.headers.putAll(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BaseApi setParams(HashMap<String, String> params) {
|
||||||
|
this.params = params;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public void useCookie(JSONObject json){
|
||||||
|
StringBuilder ck = new StringBuilder();
|
||||||
|
for (String key : json.keySet()) {
|
||||||
|
ck.append(key).append("=").append(json.getString(key)).append("; ");
|
||||||
|
}
|
||||||
|
headers.put("Cookie", ck.toString());
|
||||||
|
setHeaders(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个接口方法
|
||||||
|
*
|
||||||
|
* @param okHttpClient okhttp客户端
|
||||||
|
* @param converterFactory 处理工厂类
|
||||||
|
* @param callAdapterFactory 请求适配器工厂
|
||||||
|
* @param baseUrl 基础地质
|
||||||
|
* @param service 接口
|
||||||
|
* @param <T> 接口泛型
|
||||||
|
* @return 接口
|
||||||
|
*/
|
||||||
|
public <T> T create(OkHttpClient okHttpClient, Converter.Factory converterFactory, CallAdapter.Factory callAdapterFactory, String baseUrl, Class<T> service) {
|
||||||
|
Retrofit.Builder builder = new Retrofit.Builder()
|
||||||
|
//基础url
|
||||||
|
.baseUrl(baseUrl)
|
||||||
|
//客户端OKHttp
|
||||||
|
.client(okHttpClient);
|
||||||
|
//添加转换工厂
|
||||||
|
if (null != converterFactory) {
|
||||||
|
builder.addConverterFactory(converterFactory);
|
||||||
|
}
|
||||||
|
//添加请求工厂
|
||||||
|
if (null != callAdapterFactory) {
|
||||||
|
builder.addCallAdapterFactory(callAdapterFactory);
|
||||||
|
}
|
||||||
|
//创建retrofit对象
|
||||||
|
Retrofit retrofit = builder.build();
|
||||||
|
|
||||||
|
//返回创建的api
|
||||||
|
return retrofit.create(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T createApi(Class<T> apiClass) {
|
||||||
|
Gson gson = new GsonBuilder()
|
||||||
|
.registerTypeAdapter(Date.class, new DateTypeAdapter())
|
||||||
|
.create();
|
||||||
|
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("http");
|
||||||
|
loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);
|
||||||
|
OkHttpClient.Builder builder = new OkHttpClient()
|
||||||
|
.newBuilder()
|
||||||
|
.addInterceptor(initQuery())
|
||||||
|
.addInterceptor(loggingInterceptor);
|
||||||
|
|
||||||
|
return create(builder.build(),
|
||||||
|
JsonConverterFactory.create(gson),
|
||||||
|
JsonCallAdapter.create(),
|
||||||
|
URL,
|
||||||
|
apiClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Interceptor initQuery() {
|
||||||
|
Interceptor addQueryParameterInterceptor = new Interceptor() {
|
||||||
|
@Override
|
||||||
|
public Response intercept(Chain chain) throws IOException {
|
||||||
|
Request request = chain.request();
|
||||||
|
//配置公共参数
|
||||||
|
request = new ParamsContext(headers, params, request).getInRequest();
|
||||||
|
return chain.proceed(request);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return addQueryParameterInterceptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.yutou.okhttp.converter;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import retrofit2.CallAdapter;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class JsonCallAdapter extends CallAdapter.Factory{
|
||||||
|
public static JsonCallAdapter create(){
|
||||||
|
return new JsonCallAdapter();
|
||||||
|
}
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public CallAdapter<?, ?> get(Type type, Annotation[] annotations, Retrofit retrofit) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.yutou.okhttp.converter;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import retrofit2.Converter;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class JsonConverterFactory extends Converter.Factory {
|
||||||
|
Gson gson;
|
||||||
|
public static JsonConverterFactory create(Gson gson) {
|
||||||
|
return new JsonConverterFactory(gson);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonConverterFactory(Gson gson) {
|
||||||
|
this.gson = gson;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
|
||||||
|
// return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
|
||||||
|
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
|
||||||
|
return new JsonRequestBodyConverter<>(gson,adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
|
||||||
|
// return super.responseBodyConverter(type, annotations, retrofit);
|
||||||
|
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
|
||||||
|
return new JsonResponseBodyConverter<>(gson,adapter,type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.yutou.okhttp.converter;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okio.Buffer;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import retrofit2.Converter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
|
||||||
|
Gson gson;
|
||||||
|
TypeAdapter<T> adapter;
|
||||||
|
public JsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
|
||||||
|
this.gson=gson;
|
||||||
|
this.adapter=adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public RequestBody convert(T value) throws IOException {
|
||||||
|
Buffer buffer = new Buffer();
|
||||||
|
Writer writer = new OutputStreamWriter(buffer.outputStream(), StandardCharsets.UTF_8);
|
||||||
|
JsonWriter jsonWriter = gson.newJsonWriter(writer);
|
||||||
|
adapter.write(jsonWriter, value);
|
||||||
|
jsonWriter.close();
|
||||||
|
byte[] bytes = buffer.readByteArray();
|
||||||
|
return RequestBody.create(MediaType.parse("application/json; charset=UTF-8"),bytes );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.yutou.okhttp.converter;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.alibaba.fastjson2.JSONReader;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.yutou.okhttp.FileBody;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import retrofit2.Converter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
|
||||||
|
Gson gson;
|
||||||
|
TypeAdapter<?> adapter;
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
public JsonResponseBodyConverter(Gson gson, TypeAdapter<?> adapter, Type type) {
|
||||||
|
this.gson = gson;
|
||||||
|
this.adapter = adapter;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public T convert(ResponseBody responseBody) throws IOException {
|
||||||
|
if (type.getTypeName().contains(HttpBody.class.getSimpleName())) {
|
||||||
|
String string = new String(responseBody.bytes());
|
||||||
|
responseBody.close();
|
||||||
|
HttpBody<T> body;
|
||||||
|
try {
|
||||||
|
body = JSONObject.parseObject(string, type, JSONReader.Feature.FieldBased);
|
||||||
|
body.setSrc(string);
|
||||||
|
return (T) body;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
body = new HttpBody();
|
||||||
|
body.setSrc(string);
|
||||||
|
}
|
||||||
|
return (T) body;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
FileBody<T> body=new FileBody<T>();
|
||||||
|
body.setInputStream(responseBody.byteStream());
|
||||||
|
return (T) body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.utils;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.Cookie;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.xml.bind.DatatypeConverter;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@@ -26,7 +27,7 @@ public class AppTools {
|
|||||||
writer.close();
|
writer.close();
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,7 +167,7 @@ public class AppTools {
|
|||||||
public static String deleteCookie(HttpServletRequest request, HttpServletResponse response, String key) {
|
public static String deleteCookie(HttpServletRequest request, HttpServletResponse response, String key) {
|
||||||
for (Cookie cookie : request.getCookies()) {
|
for (Cookie cookie : request.getCookies()) {
|
||||||
if (cookie.getName().equals(key)) {
|
if (cookie.getName().equals(key)) {
|
||||||
com.yutou.bilibili.Tools.Log.i("删除key=" + key);
|
Log.i("删除key=" + key);
|
||||||
cookie.setMaxAge(0);
|
cookie.setMaxAge(0);
|
||||||
cookie.setPath("/");
|
cookie.setPath("/");
|
||||||
cookie.setValue(null);
|
cookie.setValue(null);
|
||||||
@@ -249,7 +250,7 @@ public class AppTools {
|
|||||||
digest.update(data.getBytes());
|
digest.update(data.getBytes());
|
||||||
return DatatypeConverter.printHexBinary(digest.digest());
|
return DatatypeConverter.printHexBinary(digest.digest());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -278,7 +279,7 @@ public class AppTools {
|
|||||||
|
|
||||||
}else{
|
}else{
|
||||||
if(srcFileName.equals("Activity.smali")){
|
if(srcFileName.equals("Activity.smali")){
|
||||||
com.yutou.bilibili.Tools.Log.i("文件夹已存在:"+destFileName);
|
Log.i("文件夹已存在:"+destFileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,10 +303,10 @@ public class AppTools {
|
|||||||
in.close();
|
in.close();
|
||||||
return true;
|
return true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
return false;
|
return false;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
34
common/src/main/java/com/yutou/utils/Base64Tools.java
Normal file
34
common/src/main/java/com/yutou/utils/Base64Tools.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.yutou.utils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class Base64Tools {
|
||||||
|
public static String encode(String str) {
|
||||||
|
return Base64.getEncoder().encodeToString(str.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decode(String str) {
|
||||||
|
return new String(Base64.getDecoder().decode(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encode(byte[] bytes) {
|
||||||
|
return Base64.getEncoder().encodeToString(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encode(File file) {
|
||||||
|
try {
|
||||||
|
byte[] fileContent = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
|
||||||
|
return encode(fileContent);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.utils;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
@@ -11,6 +12,10 @@ public class ConfigTools {
|
|||||||
public static final String CONFIG="config.json";
|
public static final String CONFIG="config.json";
|
||||||
public static final String DATA="data.json";
|
public static final String DATA="data.json";
|
||||||
public static final String SQLITE="sqlite.json";
|
public static final String SQLITE="sqlite.json";
|
||||||
|
|
||||||
|
public static final String NAPCAT_URL = "napcat.url";
|
||||||
|
public static final String QQ = "qq_bot";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
File file=new File(CONFIG);
|
File file=new File(CONFIG);
|
||||||
@@ -23,7 +28,7 @@ public class ConfigTools {
|
|||||||
}
|
}
|
||||||
file=null;
|
file=null;
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -68,7 +73,7 @@ public class ConfigTools {
|
|||||||
writer.close();
|
writer.close();
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +89,7 @@ public class ConfigTools {
|
|||||||
return str.toString();
|
return str.toString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.i("error = "+file.getAbsolutePath());
|
Log.i("error = "+file.getAbsolutePath());
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.utils;
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -8,15 +8,17 @@ import java.util.logging.Level;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class Log {
|
public class Log {
|
||||||
private static Logger logger;
|
private static Logger logger=Logger.getLogger("Biliob");
|
||||||
|
|
||||||
public static void i(String tag, Object log) {
|
public static void i(String tag, Object log) {
|
||||||
i('[' + tag + ']' + log);
|
i('[' + tag + ']' + log);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void i(Object log) {
|
public static void i(Object log) {
|
||||||
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout"))) {
|
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logcat"))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// logger.log(Level.INFO, log.toString());
|
||||||
System.out.printf("[%s]%s%n",
|
System.out.printf("[%s]%s%n",
|
||||||
AppTools.getToDayNowTimeToString(),
|
AppTools.getToDayNowTimeToString(),
|
||||||
log
|
log
|
||||||
@@ -25,7 +27,7 @@ public class Log {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void e(Exception e) {
|
public static void e(Exception e) {
|
||||||
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout"))) {
|
if (!ConfigTools.load(ConfigTools.CONFIG, "logcat", Boolean.class)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i(e.getMessage());
|
i(e.getMessage());
|
||||||
@@ -34,7 +36,7 @@ public class Log {
|
|||||||
|
|
||||||
public static void i(String timer, int roomId, Object log) {
|
public static void i(String timer, int roomId, Object log) {
|
||||||
String logFlag = RedisTools.get("live-log", 1);
|
String logFlag = RedisTools.get("live-log", 1);
|
||||||
if (logFlag!=null&&logFlag.startsWith("true")) {
|
if (logFlag != null && logFlag.startsWith("true")) {
|
||||||
if (logFlag.contains("|")) {
|
if (logFlag.contains("|")) {
|
||||||
if (log.toString().contains(logFlag.split("\\|")[1])) {
|
if (log.toString().contains(logFlag.split("\\|")[1])) {
|
||||||
getLogger("[" + timer.replace(":", "_") + "]" + roomId).log(Level.INFO, log.toString());
|
getLogger("[" + timer.replace(":", "_") + "]" + roomId).log(Level.INFO, log.toString());
|
||||||
136
common/src/main/java/com/yutou/utils/RSAUtils.java
Normal file
136
common/src/main/java/com/yutou/utils/RSAUtils.java
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
package com.yutou.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class RSAUtils {
|
||||||
|
/**
|
||||||
|
* 加密算法RSA
|
||||||
|
*/
|
||||||
|
public static final String KEY_ALGORITHM = "RSA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名算法
|
||||||
|
*/
|
||||||
|
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取公钥的key
|
||||||
|
*/
|
||||||
|
private static final String PUBLIC_KEY = "RSAPublicKey";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取私钥的key
|
||||||
|
*/
|
||||||
|
private static final String PRIVATE_KEY = "RSAPrivateKey";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA 密钥位数
|
||||||
|
*/
|
||||||
|
private static final int KEY_SIZE = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA最大解密密文大小
|
||||||
|
*/
|
||||||
|
private static final int MAX_DECRYPT_BLOCK = KEY_SIZE / 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA最大加密明文大小
|
||||||
|
*/
|
||||||
|
private static final int MAX_ENCRYPT_BLOCK = MAX_DECRYPT_BLOCK - 11;
|
||||||
|
private static Map<Integer,String> keyMap=new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 随机生成密钥对
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
|
*/
|
||||||
|
public static void getKeyPair() throws Exception {
|
||||||
|
//KeyPairGenerator类用于生成公钥和密钥对,基于RSA算法生成对象
|
||||||
|
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
|
||||||
|
//初始化密钥对生成器,密钥大小为96-1024位
|
||||||
|
keyPairGen.initialize(1024,new SecureRandom());
|
||||||
|
//生成一个密钥对,保存在keyPair中
|
||||||
|
KeyPair keyPair = keyPairGen.generateKeyPair();
|
||||||
|
PrivateKey privateKey = keyPair.getPrivate();//得到私钥
|
||||||
|
PublicKey publicKey = keyPair.getPublic();//得到公钥
|
||||||
|
//得到公钥字符串
|
||||||
|
String publicKeyString=new String(Base64.encodeBase64(publicKey.getEncoded()));
|
||||||
|
//得到私钥字符串
|
||||||
|
String privateKeyString=new String(Base64.encodeBase64(privateKey.getEncoded()));
|
||||||
|
//将公钥和私钥保存到Map
|
||||||
|
keyMap.put(0,publicKeyString);//0表示公钥
|
||||||
|
keyMap.put(1,privateKeyString);//1表示私钥
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 公钥加密
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param str 源数据
|
||||||
|
* @param publicKey 公钥(BASE64编码)
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static String encryptByPublicKey(String str, String publicKey) throws Exception {
|
||||||
|
publicKey=publicKey.replace("-----BEGIN PUBLIC KEY-----","").replace("-----END PUBLIC KEY-----","");
|
||||||
|
byte[] data=Base64.decodeBase64(str);
|
||||||
|
byte[] keyBytes = Base64.decodeBase64(publicKey);
|
||||||
|
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||||
|
Key publicK = keyFactory.generatePublic(x509KeySpec);
|
||||||
|
// 对数据加密
|
||||||
|
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicK);
|
||||||
|
int inputLen = data.length;
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
int offSet = 0;
|
||||||
|
byte[] cache;
|
||||||
|
int i = 0;
|
||||||
|
// 对数据分段加密
|
||||||
|
while (inputLen - offSet > 0) {
|
||||||
|
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
|
||||||
|
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
|
||||||
|
} else {
|
||||||
|
cache = cipher.doFinal(data, offSet, inputLen - offSet);
|
||||||
|
}
|
||||||
|
out.write(cache, 0, cache.length);
|
||||||
|
i++;
|
||||||
|
offSet = i * MAX_ENCRYPT_BLOCK;
|
||||||
|
}
|
||||||
|
byte[] encryptedData = out.toByteArray();
|
||||||
|
out.close();
|
||||||
|
return new String(Base64.encodeBase64(encryptedData));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA私钥解密
|
||||||
|
*
|
||||||
|
* @param str
|
||||||
|
* 加密字符串
|
||||||
|
* @param privateKey
|
||||||
|
* 私钥
|
||||||
|
* @return 铭文
|
||||||
|
* @throws Exception
|
||||||
|
* 解密过程中的异常信息
|
||||||
|
*/
|
||||||
|
public static String decrypt(String str,String privateKey) throws Exception {
|
||||||
|
//Base64解码加密后的字符串
|
||||||
|
byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
|
||||||
|
//Base64编码的私钥
|
||||||
|
byte[] decoded = Base64.decodeBase64(privateKey);
|
||||||
|
PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
|
||||||
|
//RSA解密
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE,priKey);
|
||||||
|
String outStr=new String(cipher.doFinal(inputByte));
|
||||||
|
return outStr;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.utils;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.yutou.bilibili.QQBot.QQBotManager;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
import redis.clients.jedis.JedisPoolConfig;
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
import redis.clients.jedis.JedisPubSub;
|
import redis.clients.jedis.JedisPubSub;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
public class RedisTools {
|
public class RedisTools {
|
||||||
|
public static final int QQBOT_USER = 3;
|
||||||
|
public static final String BILI_USER_BUVID = "bili_user_buvid";
|
||||||
private static boolean isNotInstallRedis = false;
|
private static boolean isNotInstallRedis = false;
|
||||||
private static String host;
|
private static String host;
|
||||||
private static int port;
|
private static int port;
|
||||||
@@ -30,7 +29,7 @@ public class RedisTools {
|
|||||||
//Properties properties = PropertyUtil.loadProperties("jedis.properties");
|
//Properties properties = PropertyUtil.loadProperties("jedis.properties");
|
||||||
//host = properties.getProperty("redis.host");
|
//host = properties.getProperty("redis.host");
|
||||||
//port = Integer.valueOf(properties.getProperty("redis.port"));
|
//port = Integer.valueOf(properties.getProperty("redis.port"));
|
||||||
host = "127.0.0.1";
|
host = "172.22.81.254";
|
||||||
port = 6379;
|
port = 6379;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,8 +50,8 @@ public class RedisTools {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean set(String key, String value) {
|
public static boolean set(Object key, String value) {
|
||||||
return set(0, key, value);
|
return set(0, key.toString(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean set(String key, String value, int timeout) {
|
public static boolean set(String key, String value, int timeout) {
|
||||||
@@ -76,7 +75,7 @@ public class RedisTools {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String get(String key, int dbIndex) {
|
public static String get(String key, int dbIndex) {
|
||||||
String value = "-999";
|
String value = null;
|
||||||
if (isNotInstallRedis) {
|
if (isNotInstallRedis) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -91,12 +90,12 @@ public class RedisTools {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String get(String key) {
|
public static String get(Object key) {
|
||||||
return get(key, 0);
|
return get(key.toString(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean remove(String key) {
|
public static boolean remove(Object key) {
|
||||||
return remove(key,0);
|
return remove(key.toString(),0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeLoginState(String uid) {
|
public static void removeLoginState(String uid) {
|
||||||
@@ -117,12 +116,12 @@ public class RedisTools {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean exists(String key, String value) {
|
public static boolean exists(Object key, String value) {
|
||||||
if (isNotInstallRedis) {
|
if (isNotInstallRedis) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Jedis jedis = getRedis();
|
Jedis jedis = getRedis();
|
||||||
boolean flag = value.equals(jedis.get(key));
|
boolean flag = value.equals(jedis.get(key.toString()));
|
||||||
jedis.close();
|
jedis.close();
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
@@ -183,53 +182,7 @@ public class RedisTools {
|
|||||||
|
|
||||||
private static boolean init = false;
|
private static boolean init = false;
|
||||||
|
|
||||||
public static void initRedisPoolSub() {
|
|
||||||
if (init)
|
|
||||||
return;
|
|
||||||
init = true;
|
|
||||||
Log.i("初始化订阅");
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Jedis jedis = getPoolRedis();
|
|
||||||
if (jedis != null)
|
|
||||||
jedis.psubscribe(new Consumer(), "*");
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class Consumer extends JedisPubSub {
|
|
||||||
@Override
|
|
||||||
public void onPMessage(String pattern, String channel, String message) {
|
|
||||||
super.onPMessage(pattern, channel, message);
|
|
||||||
Log.i("onPMessage: channel=" + channel + " msg=" + message + " pattern=" + pattern);
|
|
||||||
switch (channel) {
|
|
||||||
case "bot":
|
|
||||||
bot(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(String channel, String message) {
|
|
||||||
super.onMessage(channel, message);
|
|
||||||
Log.i("onMessage: channel=" + channel + " msg=" + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void bot(String value) {
|
|
||||||
switch (value) {
|
|
||||||
case "getip":
|
|
||||||
JSONObject json = JSONObject.parseObject(HttpTools.get("https://api.asilu.com/ip/"));
|
|
||||||
String ip = json.getString("ip");
|
|
||||||
QQBotManager.getInstance().sendMessage("服务器IP:\n" + ip);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
RedisTools.pullMsg("msg", "abc");
|
RedisTools.pullMsg("msg", "abc");
|
||||||
}
|
}
|
||||||
65
pom.xml
65
pom.xml
@@ -5,16 +5,22 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>2.4.3</version>
|
<version>3.3.0</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.yutou</groupId>
|
<groupId>com.yutou</groupId>
|
||||||
<artifactId>bilibili</artifactId>
|
<artifactId>bilibili</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
<name>bilibili</name>
|
<name>bilibili</name>
|
||||||
<description>Demo project for Spring Boot</description>
|
<description>Demo project for Spring Boot</description>
|
||||||
|
<modules>
|
||||||
|
<module>biliapi</module>
|
||||||
|
<module>qqbot</module>
|
||||||
|
<module>common</module>
|
||||||
|
</modules>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>21</java.version>
|
||||||
<kotlin.version>1.6.10</kotlin.version>
|
<kotlin.version>1.6.10</kotlin.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -26,9 +32,9 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web-services</artifactId>
|
<artifactId>spring-boot-starter-web-services</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -52,9 +58,9 @@
|
|||||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson2</artifactId>
|
||||||
<version>1.2.80</version>
|
<version>2.0.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.xerial</groupId>
|
<groupId>org.xerial</groupId>
|
||||||
@@ -64,18 +70,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.18.22</version>
|
<scope>annotationProcessor</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.java-websocket</groupId>
|
<groupId>org.java-websocket</groupId>
|
||||||
<artifactId>Java-WebSocket</artifactId>
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
<version>1.5.2</version>
|
<version>1.5.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mybatis.spring.boot</groupId>
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
@@ -103,27 +104,25 @@
|
|||||||
<version>4.1.2</version>
|
<version>4.1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.mamoe</groupId>
|
|
||||||
<artifactId>mirai-core-jvm</artifactId>
|
|
||||||
<version>2.10.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlinx</groupId>
|
|
||||||
<artifactId>kotlinx-coroutines-jdk8</artifactId>
|
|
||||||
<version>1.6.0-native-mt</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlinx</groupId>
|
|
||||||
<artifactId>kotlinx-coroutines-core-jvm</artifactId>
|
|
||||||
<version>1.6.0-native-mt</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
|
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>redis.clients</groupId>
|
<groupId>redis.clients</groupId>
|
||||||
<artifactId>jedis</artifactId>
|
<artifactId>jedis</artifactId>
|
||||||
<version>4.2.0</version>
|
<version>4.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yutou</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yutou</groupId>
|
||||||
|
<artifactId>qqbot</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -190,6 +189,14 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>7</source>
|
||||||
|
<target>7</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
|
|||||||
29
qqbot/pom.xml
Normal file
29
qqbot/pom.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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.yutou</groupId>
|
||||||
|
<artifactId>bilibili</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>qqbot</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <dependency>
|
||||||
|
<groupId>com.yutou</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>-->
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
57
qqbot/src/main/java/com/yutou/napcat/NapCatQQ.java
Normal file
57
qqbot/src/main/java/com/yutou/napcat/NapCatQQ.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package com.yutou.napcat;
|
||||||
|
|
||||||
|
import com.yutou.napcat.handle.MessageHandleBuild;
|
||||||
|
import com.yutou.napcat.handle.Text;
|
||||||
|
import com.yutou.napcat.http.NapCatApi;
|
||||||
|
import com.yutou.napcat.model.SendMessageResponse;
|
||||||
|
import com.yutou.okhttp.HttpCallback;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class NapCatQQ {
|
||||||
|
|
||||||
|
|
||||||
|
private NapCatQQ() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
/* List<BaseHandle<?>> list = new ArrayList<>();
|
||||||
|
list.add(new Text("1", false));
|
||||||
|
list.add(new Text("2", false));
|
||||||
|
list.add(new Text("3"));
|
||||||
|
list.add(new Text("4", false));
|
||||||
|
list.add(new At(583819556L));
|
||||||
|
list.add(new Text("5"));
|
||||||
|
QQBotManager.getInstance().sendMessage(false, 891655174L, list);*/
|
||||||
|
NapCatApi.setLog(false);
|
||||||
|
File file = new File("C:\\Users\\58381\\Downloads\\0074TT8Yly1hp5mqidwqeg30g20f27wh.gif");
|
||||||
|
NapCatApi.getMessageApi().sendPrivateMsg(
|
||||||
|
MessageHandleBuild.create()
|
||||||
|
.setQQNumber(583819556L)
|
||||||
|
//.add(new Image(file))
|
||||||
|
.add(new Text("abc"))
|
||||||
|
.build()
|
||||||
|
).enqueue(new HttpCallback<SendMessageResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, SendMessageResponse response, String rawResponse) {
|
||||||
|
System.out.println("code = " + code + ", status = " + status + ", response = " + response + ", rawResponse = " + rawResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
throwable.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 私聊
|
||||||
|
{"self_id":240828363,"user_id":583819556,"time":1714472684,"message_id":376,"real_id":376,"message_type":"private","sender":{"user_id":583819556,"nickname":"魔芋","card":""},"raw_message":"123","font":14,"sub_type":"friend","message":[{"data":{"text":"123"},"type":"text"}],"message_format":"array","post_type":"message"}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群聊
|
||||||
|
* {"self_id":240828363,"user_id":583819556,"time":1714472695,"message_id":377,"real_id":377,"message_type":"group","sender":{"user_id":583819556,"nickname":"魔芋","card":"","role":"owner"},"raw_message":"222","font":14,"sub_type":"normal","message":[{"data":{"text":"222"},"type":"text"}],"message_format":"array","post_type":"message","group_id":891655174}
|
||||||
|
*/
|
||||||
|
}
|
||||||
54
qqbot/src/main/java/com/yutou/napcat/QQDatabase.java
Normal file
54
qqbot/src/main/java/com/yutou/napcat/QQDatabase.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package com.yutou.napcat;
|
||||||
|
|
||||||
|
import com.yutou.napcat.model.FriendBean;
|
||||||
|
import com.yutou.napcat.model.GroupBean;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class QQDatabase {
|
||||||
|
private static Map<Long, Object> data = new HashMap<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private static FriendBean me;
|
||||||
|
|
||||||
|
public static void addUser(Long qq, FriendBean bean) {
|
||||||
|
data.put(qq, bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addGroup(Long qq, GroupBean bean) {
|
||||||
|
data.put(qq, bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkFriend(Long qq) {
|
||||||
|
if (data.containsKey(qq)) {
|
||||||
|
return data.get(qq) instanceof FriendBean;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkGroup(Long qq) {
|
||||||
|
if (data.containsKey(qq)) {
|
||||||
|
return data.get(qq) instanceof GroupBean;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<GroupBean> getGroups() {
|
||||||
|
List<GroupBean> numbers = new ArrayList<>();
|
||||||
|
for (Long qq : data.keySet()) {
|
||||||
|
if (data.get(qq) instanceof GroupBean) {
|
||||||
|
{
|
||||||
|
numbers.add((GroupBean) data.get(qq));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return numbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
145
qqbot/src/main/java/com/yutou/napcat/QQNumberManager.java
Normal file
145
qqbot/src/main/java/com/yutou/napcat/QQNumberManager.java
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
package com.yutou.napcat;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.utils.RedisTools;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class QQNumberManager {
|
||||||
|
private static QQNumberManager manager;
|
||||||
|
private QQNumberManager(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static QQNumberManager getManager() {
|
||||||
|
if(manager==null) {
|
||||||
|
manager=new QQNumberManager();
|
||||||
|
}
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
public void addNumber(Long qq,boolean isGroup){
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JSONObject json=new JSONObject();
|
||||||
|
json.put("group",isGroup);
|
||||||
|
json.put("power",new JSONArray());
|
||||||
|
json.put("model",new JSONArray());
|
||||||
|
RedisTools.set(qq,json.toJSONString());
|
||||||
|
}
|
||||||
|
public List<Long> getNumber(){
|
||||||
|
List<Long> list =new ArrayList<>();
|
||||||
|
Jedis jedis=RedisTools.getRedis();
|
||||||
|
jedis.select(RedisTools.QQBOT_USER);
|
||||||
|
Set<String> set=jedis.keys("*");
|
||||||
|
for (String s : set) {
|
||||||
|
try {
|
||||||
|
list.add(Long.parseLong(s));
|
||||||
|
}catch (Exception ignored){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jedis.close();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
public boolean addPower(Long qq, String power){
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("power");
|
||||||
|
array.add(power);
|
||||||
|
json.put("power",array);
|
||||||
|
return RedisTools.set(qq,json.toJSONString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public List<String> getPower(Long qq){
|
||||||
|
List<String> list=new ArrayList<>();
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("power");
|
||||||
|
for (Object power : array) {
|
||||||
|
list.add((String) power);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
public List<String> getUseModel(long qq) {
|
||||||
|
List<String> list=new ArrayList<>();
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("model");
|
||||||
|
for (Object power : array) {
|
||||||
|
list.add((String) power);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
public boolean delPower(Long qq, String power){
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("power");
|
||||||
|
array.remove(power);
|
||||||
|
json.put("power",array);
|
||||||
|
return RedisTools.set(qq,json.toJSONString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean addUseModel(Long qq,Class<?> modelClass){
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("model");
|
||||||
|
array.add(modelClass.getName());
|
||||||
|
json.put("model",array);
|
||||||
|
return RedisTools.set(qq,json.toJSONString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean delUseModel(Long qq,Class<?> modelClass){
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("model");
|
||||||
|
array.remove(modelClass.getName());
|
||||||
|
json.put("model",array);
|
||||||
|
return RedisTools.set(qq,json.toJSONString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean isExistsPower(Long qq, String... power){
|
||||||
|
//1
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("power");
|
||||||
|
for (String key : power) {
|
||||||
|
if(!array.contains(key)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean isGroup(Long qq){
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json= JSON.parseObject(RedisTools.get(qq));
|
||||||
|
return json.getBooleanValue("group");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean isUseModel(Long qq,Class<?> modelClass){
|
||||||
|
if(RedisTools.exists(qq,null)){
|
||||||
|
JSONObject json=JSON.parseObject(RedisTools.get(qq));
|
||||||
|
JSONArray array=json.getJSONArray("model");
|
||||||
|
return array.contains(modelClass.getName());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
29
qqbot/src/main/java/com/yutou/napcat/enums/MessageEnum.java
Normal file
29
qqbot/src/main/java/com/yutou/napcat/enums/MessageEnum.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package com.yutou.napcat.enums;
|
||||||
|
|
||||||
|
public enum MessageEnum {
|
||||||
|
TEXT("text"),
|
||||||
|
IMAGE("image"),
|
||||||
|
AT("at"),
|
||||||
|
REPLY("reply"),
|
||||||
|
JSON("json");
|
||||||
|
|
||||||
|
String type;
|
||||||
|
|
||||||
|
MessageEnum(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageEnum of(String type) {
|
||||||
|
for (MessageEnum messageEnum : MessageEnum.values()) {
|
||||||
|
if (messageEnum.getType().equals(type)) {
|
||||||
|
return messageEnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.yutou.napcat.enums;
|
||||||
|
|
||||||
|
public enum RecordFormatEnum {
|
||||||
|
MP3("mp3"),
|
||||||
|
AMR("amr"),
|
||||||
|
WMA("wma"),
|
||||||
|
M4A("m4a"),
|
||||||
|
SPX("spx"),
|
||||||
|
OGG("ogg"),
|
||||||
|
WAV("wav"),
|
||||||
|
FLAC("flac");
|
||||||
|
|
||||||
|
|
||||||
|
private final String format;
|
||||||
|
|
||||||
|
RecordFormatEnum(String format) {
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.yutou.napcat.event;
|
||||||
|
|
||||||
|
import com.yutou.napcat.model.GroupFrom;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class GroupMessageEvent extends MessageEvent {
|
||||||
|
private GroupFrom group;
|
||||||
|
|
||||||
|
}
|
||||||
183
qqbot/src/main/java/com/yutou/napcat/event/MessageEvent.java
Normal file
183
qqbot/src/main/java/com/yutou/napcat/event/MessageEvent.java
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
package com.yutou.napcat.event;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.napcat.QQDatabase;
|
||||||
|
import com.yutou.napcat.enums.MessageEnum;
|
||||||
|
import com.yutou.napcat.handle.*;
|
||||||
|
import com.yutou.napcat.model.SourceFrom;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class MessageEvent {
|
||||||
|
|
||||||
|
@JSONField(name = "self_id")
|
||||||
|
private Long selfId;
|
||||||
|
|
||||||
|
@JSONField(name = "user_id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@JSONField(name = "time")
|
||||||
|
private Long time;
|
||||||
|
|
||||||
|
@JSONField(name = "message_id")
|
||||||
|
private Integer messageId;
|
||||||
|
|
||||||
|
@JSONField(name = "real_id")
|
||||||
|
private Integer realId;
|
||||||
|
|
||||||
|
@JSONField(name = "message_type")
|
||||||
|
private String messageType;
|
||||||
|
|
||||||
|
@JSONField(name = "sender")
|
||||||
|
private SourceFrom source;
|
||||||
|
|
||||||
|
@JSONField(name = "raw_message")
|
||||||
|
private String rawMessage;
|
||||||
|
|
||||||
|
@JSONField(name = "font")
|
||||||
|
private Integer font;
|
||||||
|
|
||||||
|
@JSONField(name = "sub_type")
|
||||||
|
private String subType;
|
||||||
|
|
||||||
|
@JSONField(name = "message")
|
||||||
|
private List<BaseHandle<?>> message;
|
||||||
|
|
||||||
|
@JSONField(name = "message_format")
|
||||||
|
private String messageFormat;
|
||||||
|
|
||||||
|
@JSONField(name = "post_type")
|
||||||
|
private String postType;
|
||||||
|
|
||||||
|
@JSONField(name = "group_id")
|
||||||
|
private Long groupId;
|
||||||
|
|
||||||
|
|
||||||
|
public static MessageEvent parseHandleHttp(String jsonString) {
|
||||||
|
|
||||||
|
return parseHandle(JSONObject.parseObject(jsonString).getJSONObject("data").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageEvent parseHandle(String jsonString) {
|
||||||
|
JSONObject json = JSONObject.parseObject(jsonString);
|
||||||
|
|
||||||
|
JSONArray array = json.getJSONArray("message");
|
||||||
|
List<BaseHandle<?>> messageList = new ArrayList<>();
|
||||||
|
for (Object o : array) {
|
||||||
|
JSONObject _json = (JSONObject) o;
|
||||||
|
Type classType = null;
|
||||||
|
MessageEnum _type = MessageEnum.of(_json.getString("type"));
|
||||||
|
classType = switch (_type) {
|
||||||
|
case TEXT -> Text.TextInfo.class;
|
||||||
|
case IMAGE -> Image.ImageInfo.class;
|
||||||
|
case AT -> At.AtData.class;
|
||||||
|
case JSON -> OtherHandle.OtherInfo.class;
|
||||||
|
case REPLY -> Reply.ReplyInfo.class;
|
||||||
|
default -> classType;
|
||||||
|
};
|
||||||
|
BaseHandle<?> handle = new BaseHandle<>(_type.getType());
|
||||||
|
if (_type == MessageEnum.JSON) {
|
||||||
|
handle.setData(JSONObject.parseObject(((JSONObject) o).getJSONObject("data").getString("data"), classType));
|
||||||
|
} else {
|
||||||
|
handle.setData(JSONObject.parseObject(((JSONObject) o).getJSONObject("data").toString(), classType));
|
||||||
|
}
|
||||||
|
messageList.add(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SourceFrom sender = new SourceFrom();
|
||||||
|
sender.setUserId(json.getJSONObject("sender").getLong("user_id"));
|
||||||
|
sender.setNickname(json.getJSONObject("sender").getString("nickname"));
|
||||||
|
sender.setCard(json.getJSONObject("sender").getString("card"));
|
||||||
|
|
||||||
|
MessageEvent event = new MessageEvent();
|
||||||
|
event.setSelfId(json.getLong("self_id"));
|
||||||
|
event.setUserId(json.getLong("user_id"));
|
||||||
|
event.setTime(json.getLong("time"));
|
||||||
|
event.setMessageId(json.getInteger("message_id"));
|
||||||
|
event.setRealId(json.getInteger("real_id"));
|
||||||
|
event.setMessageType(json.getString("message_type"));
|
||||||
|
event.setSource(sender);
|
||||||
|
event.setRawMessage(json.getString("raw_message"));
|
||||||
|
event.setFont(json.getInteger("font"));
|
||||||
|
event.setSubType(json.getString("sub_type"));
|
||||||
|
event.setMessageFormat(json.getString("message_format"));
|
||||||
|
event.setPostType(json.getString("post_type"));
|
||||||
|
event.setGroupId(json.getLong("group_id"));
|
||||||
|
event.setMessage(messageList);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasType(MessageEnum messageEnum) {
|
||||||
|
for (BaseHandle<?> handle : message) {
|
||||||
|
if (MessageEnum.of(handle.getType()) == messageEnum) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BaseHandle> List<T> findAllType(Class<T> t) {
|
||||||
|
List<T> tmp = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
T newed = t.getDeclaredConstructor().newInstance();
|
||||||
|
for (BaseHandle<?> baseHandle : message) {
|
||||||
|
if (baseHandle.getType().equals(newed.getType())) {
|
||||||
|
newed.setData(baseHandle.getData());
|
||||||
|
tmp.add(newed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends BaseHandle> T findType(Class<T> tClass) {
|
||||||
|
List<T> list = findAllType(tClass);
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isAtMe() {
|
||||||
|
if (!hasType(MessageEnum.AT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
List<At> list = findAllType(At.class);
|
||||||
|
for (At handle : list) {
|
||||||
|
if (handle.getData().getQq() == QQDatabase.getMe().getUserId()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTextMessage() {
|
||||||
|
val texts = findAllType(Text.class);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Text text : texts) {
|
||||||
|
sb.append(text);
|
||||||
|
}
|
||||||
|
return sb.toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUser() {
|
||||||
|
return "private".equals(messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGroup() {
|
||||||
|
return "group".equals(messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
32
qqbot/src/main/java/com/yutou/napcat/handle/At.java
Normal file
32
qqbot/src/main/java/com/yutou/napcat/handle/At.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
public class At extends BaseHandle<At.AtData> {
|
||||||
|
public At() {
|
||||||
|
super("at");
|
||||||
|
}
|
||||||
|
|
||||||
|
public At(Long userId) {
|
||||||
|
super("at");
|
||||||
|
data = new AtData(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return String.format("[CQ:at,qq=%d]", data.qq);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AtData extends BaseBean {
|
||||||
|
private Long qq;
|
||||||
|
|
||||||
|
public AtData(Long qq) {
|
||||||
|
this.qq = qq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
qqbot/src/main/java/com/yutou/napcat/handle/BaseHandle.java
Normal file
22
qqbot/src/main/java/com/yutou/napcat/handle/BaseHandle.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class BaseHandle<T> extends BaseBean {
|
||||||
|
protected String type;
|
||||||
|
protected T data;
|
||||||
|
protected String src;
|
||||||
|
|
||||||
|
public BaseHandle(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BaseHandle(String type, Object obj) {
|
||||||
|
super();
|
||||||
|
this.type = type;
|
||||||
|
this.data= (T) obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
qqbot/src/main/java/com/yutou/napcat/handle/Image.java
Normal file
35
qqbot/src/main/java/com/yutou/napcat/handle/Image.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.utils.Base64Tools;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class Image extends BaseHandle<Image.ImageInfo> {
|
||||||
|
|
||||||
|
public Image() {
|
||||||
|
super("image");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image(String imageUrl) {
|
||||||
|
super("image");
|
||||||
|
data = new ImageInfo(imageUrl);
|
||||||
|
}
|
||||||
|
public Image(File imageFile){
|
||||||
|
super("image");
|
||||||
|
data=new ImageInfo("base64://"+ Base64Tools.encode(imageFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ImageInfo {
|
||||||
|
String file;
|
||||||
|
String url;
|
||||||
|
@JSONField(name = "file_size")
|
||||||
|
String fileSize;
|
||||||
|
|
||||||
|
public ImageInfo(String file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class MessageHandleBuild {
|
||||||
|
private List<BaseHandle<?>> msgList = new ArrayList<>();
|
||||||
|
private long qq;
|
||||||
|
private boolean autoEscape;
|
||||||
|
private boolean isGroup;
|
||||||
|
|
||||||
|
public static MessageHandleBuild create() {
|
||||||
|
return new MessageHandleBuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MessageHandleBuild() {
|
||||||
|
msgList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageHandleBuild setQQNumber(long qq) {
|
||||||
|
this.qq = qq;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageHandleBuild setAutoEscape(boolean autoEscape) {
|
||||||
|
this.autoEscape = autoEscape;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageHandleBuild add(BaseHandle<?> msg) {
|
||||||
|
msgList.add(msg);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageHandleBuild setGroup(boolean group) {
|
||||||
|
isGroup = group;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject build() {
|
||||||
|
JSONObject json=new JSONObject();
|
||||||
|
if(isGroup){
|
||||||
|
json.put("group_id", qq);
|
||||||
|
}else {
|
||||||
|
json.put("user_id", qq);
|
||||||
|
}
|
||||||
|
json.put("auto_escape", autoEscape);
|
||||||
|
json.put("message", msgList);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
qqbot/src/main/java/com/yutou/napcat/handle/OtherHandle.java
Normal file
19
qqbot/src/main/java/com/yutou/napcat/handle/OtherHandle.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import com.yutou.napcat.model.AppShareBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
public class OtherHandle extends BaseHandle<OtherHandle.OtherInfo>{
|
||||||
|
|
||||||
|
public OtherHandle() {
|
||||||
|
super("json");
|
||||||
|
data= new OtherInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class OtherInfo extends AppShareBean{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
14
qqbot/src/main/java/com/yutou/napcat/handle/QuoteReply.java
Normal file
14
qqbot/src/main/java/com/yutou/napcat/handle/QuoteReply.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
public class QuoteReply {
|
||||||
|
private final String messageId;
|
||||||
|
|
||||||
|
public QuoteReply(String messageId) {
|
||||||
|
this.messageId = messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("[CQ:reply,id=%s]",messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
38
qqbot/src/main/java/com/yutou/napcat/handle/Record.java
Normal file
38
qqbot/src/main/java/com/yutou/napcat/handle/Record.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import com.yutou.utils.ConfigTools;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
public class Record extends BaseHandle<Record.RecordInfo> {
|
||||||
|
|
||||||
|
public Record() {
|
||||||
|
super("record");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Record(String file) {
|
||||||
|
super("record");
|
||||||
|
data = new RecordInfo(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Record(String file, boolean proxy) {
|
||||||
|
super("record");
|
||||||
|
data = new RecordInfo(file);
|
||||||
|
data.proxy = proxy ? "1" : "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class RecordInfo {
|
||||||
|
String file;
|
||||||
|
int magic;
|
||||||
|
String url;
|
||||||
|
String cache;
|
||||||
|
String proxy;
|
||||||
|
String timeout;
|
||||||
|
|
||||||
|
public RecordInfo(String file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
24
qqbot/src/main/java/com/yutou/napcat/handle/Reply.java
Normal file
24
qqbot/src/main/java/com/yutou/napcat/handle/Reply.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
public class Reply extends BaseHandle<Reply.ReplyInfo> {
|
||||||
|
|
||||||
|
public Reply() {
|
||||||
|
super("reply");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reply(long id) {
|
||||||
|
super("reply");
|
||||||
|
data = new ReplyInfo(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ReplyInfo {
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
public ReplyInfo(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
qqbot/src/main/java/com/yutou/napcat/handle/Text.java
Normal file
51
qqbot/src/main/java/com/yutou/napcat/handle/Text.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package com.yutou.napcat.handle;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
public class Text extends BaseHandle<Text.TextInfo> {
|
||||||
|
|
||||||
|
public Text() {
|
||||||
|
super("text");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text(String text) {
|
||||||
|
super("text");
|
||||||
|
data = new TextInfo(text + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text(String text, boolean isNewLine) {
|
||||||
|
super("text");
|
||||||
|
if (isNewLine) {
|
||||||
|
data = new TextInfo(text + "\n");
|
||||||
|
} else {
|
||||||
|
data = new TextInfo(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text(boolean isNewLine, String... text) {
|
||||||
|
super("text");
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String s : text) {
|
||||||
|
sb.append(s);
|
||||||
|
}
|
||||||
|
if (isNewLine) {
|
||||||
|
data = new TextInfo(sb + "\n");
|
||||||
|
} else {
|
||||||
|
data = new TextInfo(sb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return data.text.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class TextInfo {
|
||||||
|
String text;
|
||||||
|
|
||||||
|
public TextInfo(String text) {
|
||||||
|
this.text = text.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
qqbot/src/main/java/com/yutou/napcat/http/FriendApi.java
Normal file
14
qqbot/src/main/java/com/yutou/napcat/http/FriendApi.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package com.yutou.napcat.http;
|
||||||
|
|
||||||
|
import com.yutou.napcat.model.FriendBean;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface FriendApi {
|
||||||
|
@POST("/get_friend_list")
|
||||||
|
Call<HttpBody<List<FriendBean>>> getFriendList(
|
||||||
|
);
|
||||||
|
}
|
||||||
70
qqbot/src/main/java/com/yutou/napcat/http/GroupApi.java
Normal file
70
qqbot/src/main/java/com/yutou/napcat/http/GroupApi.java
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package com.yutou.napcat.http;
|
||||||
|
|
||||||
|
import com.yutou.napcat.model.GroupBean;
|
||||||
|
import com.yutou.napcat.model.GroupUserBean;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.Field;
|
||||||
|
import retrofit2.http.FormUrlEncoded;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface GroupApi {
|
||||||
|
/**
|
||||||
|
* 禁言
|
||||||
|
* @param group 群号
|
||||||
|
* @param user 用户
|
||||||
|
* @param duration 禁言时长,单位秒
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/set_group_ban")
|
||||||
|
Call<HttpBody<BaseBean>> groupBan(
|
||||||
|
@Field("group_id") long group,
|
||||||
|
@Field("user_id") long user,
|
||||||
|
@Field("duration") long duration
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁言群组全体成员
|
||||||
|
* @param group 群号
|
||||||
|
*/
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/set_group_whole_ban")
|
||||||
|
Call<HttpBody<BaseBean>> groupBanAll(
|
||||||
|
@Field("group_id") long group
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群组列表
|
||||||
|
*/
|
||||||
|
@POST("/get_group_list")
|
||||||
|
Call<HttpBody<List<GroupBean>>> getGroupList(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群组信息
|
||||||
|
*/
|
||||||
|
@POST("/get_group_info")
|
||||||
|
Call<HttpBody<GroupBean>> getGroupInfo(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群组成员信息
|
||||||
|
*/
|
||||||
|
@POST("/get_group_member_info")
|
||||||
|
Call<HttpBody<GroupUserBean>> getGroupUserInfo(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群组成员列表
|
||||||
|
* @param group 群号
|
||||||
|
*/
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/get_group_member_list")
|
||||||
|
Call<HttpBody<GroupUserBean>> getGroupUserList(
|
||||||
|
@Field("group_id") long group
|
||||||
|
);
|
||||||
|
}
|
||||||
50
qqbot/src/main/java/com/yutou/napcat/http/MessageAPI.java
Normal file
50
qqbot/src/main/java/com/yutou/napcat/http/MessageAPI.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package com.yutou.napcat.http;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.napcat.model.MessageBean;
|
||||||
|
import com.yutou.napcat.model.SendMessageResponse;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.Body;
|
||||||
|
import retrofit2.http.Field;
|
||||||
|
import retrofit2.http.FormUrlEncoded;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
|
||||||
|
public interface MessageAPI {
|
||||||
|
/**
|
||||||
|
* 发送私聊消息
|
||||||
|
* @param message {@link com.yutou.napcat.handle.MessageHandleBuild}
|
||||||
|
* @return 消息id
|
||||||
|
*/
|
||||||
|
@POST("/send_private_msg")
|
||||||
|
Call<HttpBody<SendMessageResponse>> sendPrivateMsg(
|
||||||
|
@Body
|
||||||
|
JSONObject message);
|
||||||
|
/**
|
||||||
|
* 发送群聊消息
|
||||||
|
* @param message 消息内容
|
||||||
|
* @return 消息id
|
||||||
|
*/
|
||||||
|
@POST("/send_group_msg")
|
||||||
|
Call<HttpBody<SendMessageResponse>> sendGroupMsg(
|
||||||
|
@Body
|
||||||
|
JSONObject message
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 撤回消息
|
||||||
|
* @param messageId 消息id
|
||||||
|
*/
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/delete_msg")
|
||||||
|
Call<HttpBody<BaseBean>> delMsg(
|
||||||
|
@Field("message_id") long messageId
|
||||||
|
);
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/get_msg")
|
||||||
|
Call<HttpBody<MessageBean>> getMessage(
|
||||||
|
@Field("message_id") long messageId
|
||||||
|
);
|
||||||
|
}
|
||||||
33
qqbot/src/main/java/com/yutou/napcat/http/NapCatApi.java
Normal file
33
qqbot/src/main/java/com/yutou/napcat/http/NapCatApi.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package com.yutou.napcat.http;
|
||||||
|
|
||||||
|
import com.yutou.okhttp.HttpLoggingInterceptor;
|
||||||
|
import com.yutou.okhttp.api.BaseApi;
|
||||||
|
import com.yutou.utils.ConfigTools;
|
||||||
|
|
||||||
|
public class NapCatApi extends BaseApi {
|
||||||
|
private static final String URL;
|
||||||
|
static {
|
||||||
|
URL= ConfigTools.load(ConfigTools.CONFIG,ConfigTools.NAPCAT_URL,String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NapCatApi() {
|
||||||
|
super(URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setLog(boolean log){
|
||||||
|
HttpLoggingInterceptor.setLog(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageAPI getMessageApi(){
|
||||||
|
return new NapCatApi().setURL(URL).createApi(MessageAPI.class);
|
||||||
|
}
|
||||||
|
public static UtilsApi getUtilsApi(){
|
||||||
|
return new NapCatApi().setURL(URL).createApi(UtilsApi.class);
|
||||||
|
}
|
||||||
|
public static GroupApi getGroupApi(){
|
||||||
|
return new NapCatApi().setURL(URL).createApi(GroupApi.class);
|
||||||
|
}
|
||||||
|
public static FriendApi getFriendApi(){
|
||||||
|
return new NapCatApi().setURL(URL).createApi(FriendApi.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
80
qqbot/src/main/java/com/yutou/napcat/http/UtilsApi.java
Normal file
80
qqbot/src/main/java/com/yutou/napcat/http/UtilsApi.java
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package com.yutou.napcat.http;
|
||||||
|
|
||||||
|
import com.yutou.napcat.model.*;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import com.yutou.okhttp.HttpBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.Field;
|
||||||
|
import retrofit2.http.FormUrlEncoded;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
|
||||||
|
public interface UtilsApi {
|
||||||
|
/**
|
||||||
|
* 获取语音
|
||||||
|
*
|
||||||
|
* @param fileId 收到的语音文件名(消息段的 file 参数),如 0B38145AA44505000B38145AA4450500.silk
|
||||||
|
* @param format 要转换到的格式,目前支持 mp3、amr、wma、m4a、spx、ogg、wav、flac {@link com.yutou.napcat.enums.RecordFormatEnum}
|
||||||
|
* @return 转换后的语音文件路径
|
||||||
|
*/
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/get_record")
|
||||||
|
Call<HttpBody<String>> getMessageRecord(
|
||||||
|
@Field("file") String fileId,
|
||||||
|
@Field("out_format") String format
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取图片
|
||||||
|
*
|
||||||
|
* @param fileId 收到的图片文件名(消息段的 file 参数)
|
||||||
|
* @return 下载后的图片文件路径
|
||||||
|
*/
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("/get_image")
|
||||||
|
Call<HttpBody<String>> getMessageImage(
|
||||||
|
@Field("file") String fileId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否可以发送图片
|
||||||
|
*/
|
||||||
|
@POST("/can_send_image")
|
||||||
|
Call<HttpBody<CheckSendImageBean>> checkSendImage(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否可以发送语音
|
||||||
|
*/
|
||||||
|
@POST("/can_send_record")
|
||||||
|
Call<HttpBody<CheckSendRecordBean>> checkSendRecord(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取机器人状态
|
||||||
|
*/
|
||||||
|
@POST("/get_status")
|
||||||
|
Call<HttpBody<QQBotStatusBean>> checkQQBotStatus(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取机器人版本信息
|
||||||
|
*/
|
||||||
|
@POST("/get_version_info")
|
||||||
|
Call<HttpBody<QQBotVersionBean>> checkQQBotVersion(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理缓存
|
||||||
|
*/
|
||||||
|
@POST("/clean_cache")
|
||||||
|
Call<HttpBody<BaseBean>> cleanCache(
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录信息
|
||||||
|
*/
|
||||||
|
@POST("/get_login_info")
|
||||||
|
Call<HttpBody<FriendBean>> getLoginInfo(
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
139
qqbot/src/main/java/com/yutou/napcat/model/AppShareBean.java
Normal file
139
qqbot/src/main/java/com/yutou/napcat/model/AppShareBean.java
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
|
||||||
|
public class AppShareBean extends BaseBean {
|
||||||
|
|
||||||
|
@JSONField(name = "ver")
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
@JSONField(name = "prompt")
|
||||||
|
private String prompt;
|
||||||
|
|
||||||
|
@JSONField(name = "config")
|
||||||
|
private Config config;
|
||||||
|
|
||||||
|
@JSONField(name = "needShareCallBack")
|
||||||
|
private boolean needShareCallBack;
|
||||||
|
|
||||||
|
@JSONField(name = "app")
|
||||||
|
private String app;
|
||||||
|
|
||||||
|
@JSONField(name = "view")
|
||||||
|
private String view;
|
||||||
|
|
||||||
|
@JSONField(name = "meta")
|
||||||
|
private Meta meta;
|
||||||
|
|
||||||
|
// getters and setters...
|
||||||
|
|
||||||
|
// Inner classes
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Config {
|
||||||
|
@JSONField(name = "type")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@JSONField(name = "width")
|
||||||
|
private int width;
|
||||||
|
|
||||||
|
@JSONField(name = "height")
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
@JSONField(name = "forward")
|
||||||
|
private int forward;
|
||||||
|
|
||||||
|
@JSONField(name = "autoSize")
|
||||||
|
private int autoSize;
|
||||||
|
|
||||||
|
@JSONField(name = "ctime")
|
||||||
|
private long ctime;
|
||||||
|
|
||||||
|
@JSONField(name = "token")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
// getters and setters...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Meta {
|
||||||
|
@JSONField(name = "detail_1")
|
||||||
|
private Detail detail1;
|
||||||
|
|
||||||
|
// If there can be multiple "detail_X" entries, you might need a Map
|
||||||
|
// @JSONField(name = "detail_X")
|
||||||
|
// private Map<String, Detail> details;
|
||||||
|
|
||||||
|
// getters and setters...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Detail {
|
||||||
|
@JSONField(name = "appid")
|
||||||
|
private String appid;
|
||||||
|
|
||||||
|
@JSONField(name = "appType")
|
||||||
|
private int appType;
|
||||||
|
|
||||||
|
@JSONField(name = "title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@JSONField(name = "desc")
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
@JSONField(name = "icon")
|
||||||
|
private String icon;
|
||||||
|
|
||||||
|
@JSONField(name = "preview")
|
||||||
|
private String preview;
|
||||||
|
|
||||||
|
@JSONField(name = "url")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@JSONField(name = "scene")
|
||||||
|
private int scene;
|
||||||
|
|
||||||
|
@JSONField(name = "host")
|
||||||
|
private Host host;
|
||||||
|
|
||||||
|
@JSONField(name = "shareTemplateId")
|
||||||
|
private String shareTemplateId;
|
||||||
|
|
||||||
|
// Since "shareTemplateData" is an empty object, it can be left as a Map or a specific class
|
||||||
|
// if you know the structure of the data that might be there
|
||||||
|
@JSONField(name = "shareTemplateData")
|
||||||
|
private Map<String, Object> shareTemplateData;
|
||||||
|
|
||||||
|
@JSONField(name = "qqdocurl")
|
||||||
|
private String qqdocurl;
|
||||||
|
|
||||||
|
@JSONField(name = "showLittleTail")
|
||||||
|
private String showLittleTail;
|
||||||
|
|
||||||
|
@JSONField(name = "gamePoints")
|
||||||
|
private String gamePoints;
|
||||||
|
|
||||||
|
@JSONField(name = "gamePointsUrl")
|
||||||
|
private String gamePointsUrl;
|
||||||
|
|
||||||
|
// getters and setters...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Host {
|
||||||
|
@JSONField(name = "uin")
|
||||||
|
private long uin;
|
||||||
|
|
||||||
|
@JSONField(name = "nick")
|
||||||
|
private String nick;
|
||||||
|
|
||||||
|
// getters and setters...
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CheckSendImageBean extends BaseBean {
|
||||||
|
@JSONField(name = "yes")
|
||||||
|
private boolean yes;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CheckSendRecordBean extends BaseBean {
|
||||||
|
@JSONField(name = "yes")
|
||||||
|
private boolean yes;
|
||||||
|
|
||||||
|
}
|
||||||
15
qqbot/src/main/java/com/yutou/napcat/model/FriendBean.java
Normal file
15
qqbot/src/main/java/com/yutou/napcat/model/FriendBean.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FriendBean extends BaseBean {
|
||||||
|
@JSONField(name = "user_id")
|
||||||
|
private long userId;//qq号
|
||||||
|
@JSONField(name = "nickname")
|
||||||
|
private String nickName;//昵称
|
||||||
|
@JSONField(name = "remark")
|
||||||
|
private String remark;//备注
|
||||||
|
}
|
||||||
18
qqbot/src/main/java/com/yutou/napcat/model/GroupBean.java
Normal file
18
qqbot/src/main/java/com/yutou/napcat/model/GroupBean.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class GroupBean extends BaseBean {
|
||||||
|
@JSONField(name = "group_id")
|
||||||
|
private long groupId;
|
||||||
|
@JSONField(name = "group_name")
|
||||||
|
private String groupName;
|
||||||
|
@JSONField(name = "member_count")
|
||||||
|
private int userCount;
|
||||||
|
@JSONField(name = "max_member_count")
|
||||||
|
private int userMaxCount;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class GroupFrom {
|
||||||
|
private long id;
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class GroupUserBean extends BaseBean {
|
||||||
|
// 群号
|
||||||
|
@JSONField(name = "group_id")
|
||||||
|
private long groupId;
|
||||||
|
|
||||||
|
// QQ号
|
||||||
|
@JSONField(name = "user_id")
|
||||||
|
private long userId;
|
||||||
|
|
||||||
|
// 昵称
|
||||||
|
@JSONField(name = "nickname")
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
// 群名片/备注
|
||||||
|
@JSONField(name = "card")
|
||||||
|
private String card;
|
||||||
|
|
||||||
|
// 性别,male 或 female 或 unknown
|
||||||
|
@JSONField(name = "sex")
|
||||||
|
private String sex;
|
||||||
|
|
||||||
|
// 年龄
|
||||||
|
@JSONField(name = "age")
|
||||||
|
private int age;
|
||||||
|
|
||||||
|
// 地区
|
||||||
|
@JSONField(name = "area")
|
||||||
|
private String area;
|
||||||
|
|
||||||
|
// 加群时间戳
|
||||||
|
@JSONField(name = "join_time")
|
||||||
|
private int joinTime;
|
||||||
|
|
||||||
|
// 最后发言时间戳
|
||||||
|
@JSONField(name = "last_sent_time")
|
||||||
|
private int lastSentTime;
|
||||||
|
|
||||||
|
// 成员等级
|
||||||
|
@JSONField(name = "level")
|
||||||
|
private String level;
|
||||||
|
|
||||||
|
// 角色,owner 或 admin 或 member
|
||||||
|
@JSONField(name = "role")
|
||||||
|
private String role;
|
||||||
|
|
||||||
|
// 是否不良记录成员
|
||||||
|
@JSONField(name = "unfriendly")
|
||||||
|
private boolean unfriendly;
|
||||||
|
|
||||||
|
// 专属头衔
|
||||||
|
@JSONField(name = "title")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
// 专属头衔过期时间戳
|
||||||
|
@JSONField(name = "title_expire_time")
|
||||||
|
private int titleExpireTime;
|
||||||
|
|
||||||
|
// 是否允许修改群名片
|
||||||
|
@JSONField(name = "card_changeable")
|
||||||
|
private boolean cardChangeable;
|
||||||
|
|
||||||
|
}
|
||||||
23
qqbot/src/main/java/com/yutou/napcat/model/Message.java
Normal file
23
qqbot/src/main/java/com/yutou/napcat/model/Message.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Message {
|
||||||
|
private String message;
|
||||||
|
private String srcMessage;
|
||||||
|
private String id;
|
||||||
|
public Message(String message, String srcMessage) {
|
||||||
|
this.message = message;
|
||||||
|
this.srcMessage = srcMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String serializeToMiraiCode(){
|
||||||
|
return srcMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String contentToString(){
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
45
qqbot/src/main/java/com/yutou/napcat/model/MessageBean.java
Normal file
45
qqbot/src/main/java/com/yutou/napcat/model/MessageBean.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息
|
||||||
|
* @see <a href="https://github.com/botuniverse/onebot-11/blob/master/api/public.md#get_msg-%E8%8E%B7%E5%8F%96%E6%B6%88%E6%81%AF">文档</a>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageBean extends BaseBean {
|
||||||
|
/**
|
||||||
|
*发送时间
|
||||||
|
*/
|
||||||
|
@JSONField(name = "time")
|
||||||
|
private long time;
|
||||||
|
/**
|
||||||
|
* 消息类型,同 <a href="https://github.com/botuniverse/onebot-11/blob/master/event/message.md">消息事件</a>
|
||||||
|
*/
|
||||||
|
@JSONField(name = "message_type")
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* 消息 ID
|
||||||
|
*/
|
||||||
|
@JSONField(name = "message_id")
|
||||||
|
private int messageId;
|
||||||
|
/**
|
||||||
|
* 消息真实 ID
|
||||||
|
*/
|
||||||
|
@JSONField(name = "real_id")
|
||||||
|
private int realId;
|
||||||
|
/**
|
||||||
|
* 发送人信息,同 <a href="https://github.com/botuniverse/onebot-11/blob/master/event/message.md">消息事件</a>
|
||||||
|
*/
|
||||||
|
@JSONField(name = "sender")
|
||||||
|
private SenderBean sender;
|
||||||
|
/**
|
||||||
|
* 消息内容
|
||||||
|
*/
|
||||||
|
@JSONField(name = "message")
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.okhttp.BaseBean;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class QQBotStatusBean extends BaseBean {
|
||||||
|
@JSONField(name = "online")
|
||||||
|
private String online;//当前 QQ 在线,null 表示无法查询到在线状态
|
||||||
|
@JSONField(name = "good")
|
||||||
|
private String good;//状态符合预期,意味着各模块正常运行、功能正常,且 QQ 在线
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.yutou.napcat.model;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class QQBotVersionBean {
|
||||||
|
@JSONField(name = "app_name")
|
||||||
|
private String appName;//应用标识,如 mirai-native
|
||||||
|
|
||||||
|
@JSONField(name = "app_version")
|
||||||
|
private String appVersion;//应用版本,如 1.2.3
|
||||||
|
|
||||||
|
@JSONField(name = "protocol_version")
|
||||||
|
private String protocolVersion;//OneBot 标准版本,如 v11
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user