update
This commit is contained in:
167
src/main/java/com/yutou/biliapi/Main.java
Normal file
167
src/main/java/com/yutou/biliapi/Main.java
Normal file
@@ -0,0 +1,167 @@
|
||||
package com.yutou.biliapi;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.biliapi.api.UserApi;
|
||||
import com.yutou.biliapi.bean.live.SpiBean;
|
||||
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
|
||||
import com.yutou.biliapi.bean.login.LoginUserDatabaseBean;
|
||||
import com.yutou.biliapi.bean.login.UserInfoBean;
|
||||
import com.yutou.biliapi.net.BiliLoginNetApiManager;
|
||||
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
|
||||
import com.yutou.biliapi.net.BiliUserNetApiManager;
|
||||
import com.yutou.common.inter.IHttpApiCheckCallback;
|
||||
import com.yutou.common.okhttp.HttpBody;
|
||||
import com.yutou.common.okhttp.HttpCallback;
|
||||
import com.yutou.common.okhttp.HttpLoggingInterceptor;
|
||||
import com.yutou.common.utils.Log;
|
||||
import jakarta.xml.bind.DatatypeConverter;
|
||||
import okhttp3.Headers;
|
||||
import retrofit2.Response;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// HttpLoggingInterceptor.setLog(false);
|
||||
// HttpLoggingInterceptor.setLog(true);
|
||||
// login();
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
BiliLoginNetApiManager.getInstance().login(new HttpCallback<LoginCookieDatabaseBean>() {
|
||||
@Override
|
||||
public void onResponse(Headers headers, int code, String status, LoginCookieDatabaseBean response, String rawResponse) {
|
||||
System.out.println("二维码地址: "+rawResponse);
|
||||
if (code == BiliLoginNetApiManager.LOGIN_SUCCESS) {
|
||||
Response<HttpBody<UserInfoBean>> execute = null;
|
||||
try {
|
||||
execute = BiliUserNetApiManager.getInstance().getUserApi(response).getUserInfo().execute();
|
||||
if (execute.isSuccessful()) {
|
||||
if (execute.body() != null) {
|
||||
UserInfoBean data = execute.body().getData();
|
||||
LoginUserDatabaseBean userBean=new LoginUserDatabaseBean(data);
|
||||
BiliBiliLoginDatabase.getInstance().initData(response,userBean).close();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
62
src/main/java/com/yutou/biliapi/api/LiveApi.java
Normal file
62
src/main/java/com/yutou/biliapi/api/LiveApi.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package com.yutou.biliapi.api;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.biliapi.bean.live.*;
|
||||
import com.yutou.common.okhttp.BaseBean;
|
||||
import com.yutou.common.okhttp.FileBody;
|
||||
import com.yutou.common.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.biliapi.enums.LiveProtocol}
|
||||
* @param format 格式 {@link com.yutou.biliapi.enums.LiveVideoFormat}
|
||||
* @param codec 编码 {@link com.yutou.biliapi.enums.LiveVideoCodec}
|
||||
* @param qn 清晰度 {@link com.yutou.biliapi.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);
|
||||
|
||||
@GET("/xlive/web-room/v1/giftPanel/giftConfig?platform=pc")
|
||||
Call<HttpBody<BaseBean>> getLiveGiftConfig();
|
||||
|
||||
@POST("/room/v1/Room/get_status_info_by_uids")
|
||||
Call<HttpBody<BaseBean>> getLiveRoomStatus( @Body
|
||||
JSONObject uids);
|
||||
|
||||
}
|
||||
31
src/main/java/com/yutou/biliapi/api/LoginApi.java
Normal file
31
src/main/java/com/yutou/biliapi/api/LoginApi.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.yutou.biliapi.api;
|
||||
|
||||
import com.yutou.biliapi.bean.login.CheckCookieBean;
|
||||
import com.yutou.biliapi.bean.login.LoginInfoBean;
|
||||
import com.yutou.biliapi.bean.login.QRCodeGenerateBean;
|
||||
import com.yutou.common.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
src/main/java/com/yutou/biliapi/api/UserApi.java
Normal file
16
src/main/java/com/yutou/biliapi/api/UserApi.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.yutou.biliapi.api;
|
||||
|
||||
import com.yutou.biliapi.bean.live.SpiBean;
|
||||
import com.yutou.biliapi.bean.login.UserInfoBean;
|
||||
import com.yutou.common.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,82 @@
|
||||
package com.yutou.biliapi.bean.live;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class LiveAnchorInfo {
|
||||
/**
|
||||
* {
|
||||
* "title": "挑战最难魂系",
|
||||
* "room_id": 7688602,
|
||||
* "uid": 269415357,
|
||||
* "online": 43171,
|
||||
* "live_time": 1729049421,
|
||||
* "live_status": 1,
|
||||
* "short_id": 0,
|
||||
* "area": 6,
|
||||
* "area_name": "生活娱乐",
|
||||
* "area_v2_id": 745,
|
||||
* "area_v2_name": "虚拟Gamer",
|
||||
* "area_v2_parent_name": "虚拟主播",
|
||||
* "area_v2_parent_id": 9,
|
||||
* "uname": "花花Haya",
|
||||
* "face": "https://i0.hdslb.com/bfs/face/a269de03af269453d14eaf0dc7cc23240d69da6c.jpg",
|
||||
* "tag_name": "日常,学习,萌宠,厨艺,手机直播",
|
||||
* "tags": "唱见,虚拟主播,虚拟up主",
|
||||
* "cover_from_user": "https://i0.hdslb.com/bfs/live/new_room_cover/925b98639a8d3b62462bc699c6dbb833e27e17d5.jpg",
|
||||
* "keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe101614360000076886025wzvg0.jpg",
|
||||
* "lock_till": "0000-00-00 00:00:00",
|
||||
* "hidden_till": "0000-00-00 00:00:00",
|
||||
* "broadcast_type": 0
|
||||
* }
|
||||
*/
|
||||
@JSONField(name = "title")
|
||||
private String title;
|
||||
@JSONField(name = "room_id")
|
||||
private BigInteger roomId;
|
||||
@JSONField(name = "uid")
|
||||
private BigInteger uid;
|
||||
@JSONField(name = "online")
|
||||
private int online;
|
||||
@JSONField(name = "live_time")
|
||||
private long liveTime;
|
||||
@JSONField(name = "live_status")
|
||||
private int liveStatus;
|
||||
@JSONField(name = "short_id")
|
||||
private int shortId;
|
||||
@JSONField(name = "area")
|
||||
private int area;
|
||||
@JSONField(name = "area_name")
|
||||
private String areaName;
|
||||
@JSONField(name = "area_v2_id")
|
||||
private int areaV2Id;
|
||||
@JSONField(name = "area_v2_name")
|
||||
private String areaV2Name;
|
||||
@JSONField(name = "area_v2_parent_id")
|
||||
private int areaV2ParentId;
|
||||
@JSONField(name = "area_v2_parent_name")
|
||||
private String areaV2ParentName;
|
||||
@JSONField(name = "uname")
|
||||
private String uname;
|
||||
@JSONField(name = "face")
|
||||
private String face;//头像
|
||||
@JSONField(name = "cover_from_user")
|
||||
private String coverFromUser;//直播封面
|
||||
@JSONField(name = "tag_name")
|
||||
private String tagName;
|
||||
@JSONField(name = "tags")
|
||||
private String tags;
|
||||
@JSONField(name = "keyframe")
|
||||
private String keyframe;//直播关键帧
|
||||
@JSONField(name = "lock_till")
|
||||
private Date lockTill;
|
||||
@JSONField(name = "hidden_till")
|
||||
private Date hiddenTill;
|
||||
@JSONField(name = "broadcast_type")
|
||||
private int broadcastType;
|
||||
|
||||
}
|
||||
46
src/main/java/com/yutou/biliapi/bean/live/LiveDanmuInfo.java
Normal file
46
src/main/java/com/yutou/biliapi/bean/live/LiveDanmuInfo.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.yutou.biliapi.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,40 @@
|
||||
package com.yutou.biliapi.bean.live;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
@Data
|
||||
public class LiveRoomConfig {
|
||||
String loginUid;
|
||||
BigInteger roomId;
|
||||
String anchorName;
|
||||
boolean isLogin;
|
||||
LiveDanmuInfo liveInfo;
|
||||
LiveRoomInfo roomInfo;
|
||||
|
||||
public String getLoginUid() {
|
||||
if("null".equals(loginUid)){
|
||||
loginUid=null;
|
||||
}
|
||||
return loginUid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
LiveRoomConfig that = (LiveRoomConfig) o;
|
||||
return Objects.equals(roomId, that.roomId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(roomId);
|
||||
}
|
||||
}
|
||||
235
src/main/java/com/yutou/biliapi/bean/live/LiveRoomInfo.java
Normal file
235
src/main/java/com/yutou/biliapi/bean/live/LiveRoomInfo.java
Normal file
@@ -0,0 +1,235 @@
|
||||
package com.yutou.biliapi.bean.live;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class LiveRoomInfo {
|
||||
@JSONField(name = "uid")
|
||||
private BigInteger uid;
|
||||
|
||||
@JSONField(name = "room_id")
|
||||
private BigInteger 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;
|
||||
}
|
||||
|
||||
}
|
||||
232
src/main/java/com/yutou/biliapi/bean/live/LiveRoomPlayInfo.java
Normal file
232
src/main/java/com/yutou/biliapi/bean/live/LiveRoomPlayInfo.java
Normal file
@@ -0,0 +1,232 @@
|
||||
package com.yutou.biliapi.bean.live;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.common.okhttp.BaseBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveRoomPlayInfo extends BaseBean {
|
||||
@JSONField(name = "room_id")
|
||||
private BigInteger roomId;
|
||||
|
||||
@JSONField(name = "short_id")
|
||||
private int shortId;
|
||||
|
||||
@JSONField(name = "uid")
|
||||
private BigInteger 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,39 @@
|
||||
package com.yutou.biliapi.bean.live;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
@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 BigInteger roomid;
|
||||
|
||||
@JSONField(name = "broadcast_type")
|
||||
private int broadcastType;
|
||||
|
||||
@JSONField(name = "online_hidden")
|
||||
private int onlineHidden;
|
||||
}
|
||||
100
src/main/java/com/yutou/biliapi/bean/live/MasterInfoBean.java
Normal file
100
src/main/java/com/yutou/biliapi/bean/live/MasterInfoBean.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package com.yutou.biliapi.bean.live;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.common.okhttp.BaseBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigInteger;
|
||||
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 BigInteger 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
src/main/java/com/yutou/biliapi/bean/live/SpiBean.java
Normal file
12
src/main/java/com/yutou/biliapi/bean/live/SpiBean.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.yutou.biliapi.bean.live;
|
||||
|
||||
import com.yutou.common.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,77 @@
|
||||
package com.yutou.biliapi.bean.live.database;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveConfigDatabaseBean extends AbsDatabasesBean {
|
||||
@JSONField(name = "live_room_id")
|
||||
private BigInteger roomId;
|
||||
@JSONField(name = "anchorUid")
|
||||
private BigInteger anchorUid;
|
||||
@JSONField(name = "anchorName")
|
||||
private String anchorName;
|
||||
@JSONField(name = "anchorFace")
|
||||
private String anchorFace;
|
||||
@JSONField(name = "recordLive")
|
||||
private boolean isRecordLive;
|
||||
@JSONField(name = "recordDanmu")
|
||||
private boolean isRecordDanmu;
|
||||
@JSONField(name = "keyword")
|
||||
private List<String> keywordList;
|
||||
@JSONField(name = "recordUid")
|
||||
private String recordUid;
|
||||
@JSONField(name = "recordDanmuDate")
|
||||
private String recordDanmuDate="* * *";// * * * 分 时 星期 | 周日是1
|
||||
@JSONField(name = "recordLiveDate")
|
||||
private String recordLiveDate="* * *";// * * * 分 时 星期 | 周日是1
|
||||
|
||||
|
||||
public LiveConfigDatabaseBean() {
|
||||
super("live_config",System.currentTimeMillis());
|
||||
}
|
||||
public boolean checkRecordDanmuTime(){
|
||||
return checkRecordTime(recordDanmuDate);
|
||||
}
|
||||
public boolean checkRecordLiveTime(){
|
||||
return checkRecordTime(recordLiveDate);
|
||||
}
|
||||
private boolean checkRecordTime(String recordDate){
|
||||
int _length = recordDate.length();
|
||||
boolean isFullDate=(_length-recordDate.replace("*","").length())==3;
|
||||
if(isFullDate){
|
||||
return true;
|
||||
}
|
||||
String[] split=recordDate.split(" ");
|
||||
String minute=split[0];
|
||||
String hour=split[1];
|
||||
String day=split[2];
|
||||
boolean isFullMinute= "*".equals(minute);
|
||||
boolean isFullHour= "*".equals(hour);
|
||||
boolean isFullDay= "*".equals(day);
|
||||
Calendar today=Calendar.getInstance();
|
||||
if(!isFullDay){
|
||||
if(today.get(Calendar.DAY_OF_WEEK)!=Integer.parseInt(day)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!isFullHour) {
|
||||
if (today.get(Calendar.HOUR_OF_DAY) != Integer.parseInt(hour)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!isFullMinute){
|
||||
if(today.get(Calendar.MINUTE)!=Integer.parseInt(minute)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.yutou.biliapi.bean.live.database;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.biliapi.bean.websocket.live.WSDanmuData;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveDanmuDatabaseBean extends AbsDatabasesBean {
|
||||
@JSONField(name = "id")
|
||||
int id;
|
||||
@JSONField(name = "danmu")
|
||||
private String danmu;
|
||||
@JSONField(name = "model")
|
||||
private int model;// 1~3 滚动弹幕 4 底端弹幕 5 顶端弹幕 6 逆向弹幕 7 精准定位 8 高级弹幕
|
||||
@JSONField(name = "fontSize")
|
||||
private int fontSize;
|
||||
@JSONField(name = "color")
|
||||
private String fontColor;
|
||||
@JSONField(name = "time")
|
||||
private long time;
|
||||
@JSONField(name = "uid")
|
||||
private BigInteger uid;
|
||||
@JSONField(name = "uname")
|
||||
private String uname;
|
||||
|
||||
|
||||
|
||||
public LiveDanmuDatabaseBean() {
|
||||
super("danmu",System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public LiveDanmuDatabaseBean(WSDanmuData danmu) {
|
||||
super("danmu",danmu.getWs_timer());
|
||||
this.danmu = danmu.getDanmu();
|
||||
model = danmu.getModel();
|
||||
fontSize = danmu.getFontSize();
|
||||
fontColor = danmu.getFontColor();
|
||||
time = danmu.getTime();
|
||||
uid = danmu.getUid();
|
||||
uname = danmu.getUname();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.yutou.biliapi.bean.live.database;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.biliapi.bean.websocket.live.WSSendGift;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveGiftDatabaseBean extends AbsDatabasesBean {
|
||||
@JSONField(name = "id")
|
||||
int id;
|
||||
@JSONField(name = "gift_id")
|
||||
private int giftId;
|
||||
@JSONField(name = "gift_name")
|
||||
private String giftName;
|
||||
@JSONField(name = "price")
|
||||
private long price;
|
||||
@JSONField(name = "coin_type")
|
||||
private String coinType;
|
||||
@JSONField(name = "icon")
|
||||
private String icon;
|
||||
@JSONField(name = "gift_num")
|
||||
private int giftNum;
|
||||
@JSONField(name = "sender_uid")
|
||||
private long senderUid;
|
||||
@JSONField(name = "sender_name")
|
||||
private String senderName;
|
||||
@JSONField(name = "sender_face")
|
||||
private String senderFace;
|
||||
@JSONField(name = "send_time")
|
||||
private long sendTime;
|
||||
@JSONField(name = "action")
|
||||
private String action;
|
||||
|
||||
|
||||
public LiveGiftDatabaseBean() {
|
||||
super("gift",System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public LiveGiftDatabaseBean(WSSendGift gift) {
|
||||
super("gift",gift.getWs_timer());
|
||||
giftId = gift.getData().getGiftId();
|
||||
giftName = gift.getData().getGiftName();
|
||||
price = gift.getData().getPrice();
|
||||
coinType = gift.getData().getCoinType();
|
||||
icon = gift.getData().getGiftInfo().getWebp();
|
||||
if (gift.getData().getComboSend() != null) {
|
||||
giftNum = gift.getData().getComboSend().getGiftNum();
|
||||
} else {
|
||||
giftNum = 1;
|
||||
}
|
||||
senderUid = gift.getData().getSenderUinfo().getUid();
|
||||
senderName = gift.getData().getSenderUinfo().getBase().getName();
|
||||
senderFace = gift.getData().getSenderUinfo().getBase().getFace();
|
||||
sendTime = gift.getData().getTimestamp();
|
||||
action = gift.getData().getAction();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.yutou.biliapi.bean.live.database;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.biliapi.bean.live.LiveRoomInfo;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveInfoDatabaseBean extends AbsDatabasesBean {
|
||||
@JSONField(name = "id")
|
||||
int id;
|
||||
@JSONField(name = "roomId")
|
||||
private BigInteger roomId;
|
||||
@JSONField(name = "anchorUid")
|
||||
private BigInteger anchorUid;
|
||||
@JSONField(name = "title")
|
||||
private String title;
|
||||
@JSONField(name = "record_time_start")
|
||||
private long recordTimeStart;
|
||||
@JSONField(name = "record_time_end")
|
||||
private long recordTimeEnd;
|
||||
@JSONField(name = "cover")
|
||||
private String cover;
|
||||
@JSONField(name = "room_info")
|
||||
private String roomInfo;
|
||||
|
||||
public LiveInfoDatabaseBean(LiveRoomInfo info) {
|
||||
super("info", System.currentTimeMillis());
|
||||
roomId = info.getRoomId();
|
||||
roomInfo = JSONObject.toJSONString(info);
|
||||
recordTimeStart = System.currentTimeMillis();
|
||||
anchorUid = info.getUid();
|
||||
title = info.getTitle();
|
||||
cover = info.getUserCover();
|
||||
}
|
||||
|
||||
|
||||
public LiveInfoDatabaseBean() {
|
||||
super("info", System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Field> list = new LiveInfoDatabaseBean().getFields();
|
||||
for (Field field : list) {
|
||||
System.out.println(field.getName());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.yutou.biliapi.bean.live.database;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.biliapi.bean.websocket.live.WSInteractWord;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveInteractWordDatabaseBean extends AbsDatabasesBean {
|
||||
@JSONField(name = "id")
|
||||
int id;
|
||||
@JSONField(name = "uid")
|
||||
private long uid;
|
||||
@JSONField(name = "type")
|
||||
private int type; //1为进场,2为关注
|
||||
@JSONField(name = "room_id")
|
||||
private long roomId;
|
||||
@JSONField(name = "timer")
|
||||
private long timer;
|
||||
@JSONField(name = "uname")
|
||||
private String uname;
|
||||
@JSONField(name = "uname_color")
|
||||
private String uname_color;
|
||||
@JSONField(name = "face")
|
||||
private String face;
|
||||
|
||||
public LiveInteractWordDatabaseBean() {
|
||||
super("InteractWord",System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public LiveInteractWordDatabaseBean(WSInteractWord bean) {
|
||||
super("InteractWord", bean.getWs_timer());
|
||||
uid = bean.getUid();
|
||||
type = bean.getType();
|
||||
roomId = bean.getRoomId();
|
||||
timer = bean.getTimer();
|
||||
uname = bean.getUname();
|
||||
uname_color = bean.getUname_color();
|
||||
face = bean.getFace();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.yutou.biliapi.bean.live.database;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.biliapi.bean.websocket.live.WSData;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveSourceDatabaseBean extends AbsDatabasesBean {
|
||||
@JSONField(name = "id")
|
||||
int id;
|
||||
@JSONField(name = "type")
|
||||
private String type;
|
||||
@JSONField(name = "json")
|
||||
private String json;
|
||||
|
||||
public LiveSourceDatabaseBean() {
|
||||
super("source",System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public LiveSourceDatabaseBean(WSData bean) {
|
||||
super("source",bean.getWs_timer());
|
||||
this.json = bean.getJson();
|
||||
type = bean.getCmd();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.yutou.biliapi.bean.live.database;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.biliapi.bean.websocket.live.WSSuperChatMessage;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LiveSuperChatDatabaseBean extends AbsDatabasesBean {
|
||||
@JSONField(name = "id")
|
||||
private int id;
|
||||
@JSONField(name = "price")
|
||||
private long price;
|
||||
@JSONField(name = "uid")
|
||||
private long uid;
|
||||
@JSONField(name = "start_time")
|
||||
private long start_time;
|
||||
@JSONField(name = "end_time")
|
||||
private long end_time;
|
||||
@JSONField(name = "message")
|
||||
private String message;
|
||||
@JSONField(name = "message_trans")
|
||||
private String message_trans;
|
||||
@JSONField(name = "message_font_color")
|
||||
private String message_font_color;
|
||||
|
||||
public LiveSuperChatDatabaseBean() {
|
||||
super("superChat",System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public LiveSuperChatDatabaseBean(WSSuperChatMessage bean) {
|
||||
super("superChat",bean.getWs_timer());
|
||||
price = bean.getPrice();
|
||||
uid = bean.getUid();
|
||||
start_time = bean.getStart_time();
|
||||
end_time = bean.getEnd_time();
|
||||
message = bean.getMessage();
|
||||
message_trans = bean.getMessage_trans();
|
||||
message_font_color = bean.getMessage_font_color();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.yutou.biliapi.bean.login;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.common.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.biliapi.bean.login;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LoginCookieDatabaseBean 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 LoginCookieDatabaseBean() {
|
||||
super("login_cookie", System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.yutou.biliapi.bean.login;
|
||||
|
||||
import com.yutou.common.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,44 @@
|
||||
package com.yutou.biliapi.bean.login;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.alibaba.fastjson2.util.DateUtils;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LoginUserDatabaseBean extends AbsDatabasesBean {
|
||||
UserInfoBean userInfo;
|
||||
|
||||
public LoginUserDatabaseBean(UserInfoBean userInfo) {
|
||||
super("login_user",System.currentTimeMillis());
|
||||
this.userInfo=userInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
if(userInfo==null){
|
||||
return new JSONObject();
|
||||
}
|
||||
JSONObject json= JSONObject.parseObject(JSONObject.toJSONString(userInfo));
|
||||
json.put("sql_time", DateUtils.format(getSql_time(), "yyyy-MM-dd HH:mm:ss.SSS"));
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Field> getFields() {
|
||||
List<Field> fields = new ArrayList<>(List.of(UserInfoBean.class.getDeclaredFields()));
|
||||
for (Field field : super.getFields()) {
|
||||
if(!field.getName().contains("userInfo")){
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.yutou.biliapi.bean.login;
|
||||
|
||||
|
||||
import com.yutou.common.okhttp.BaseBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class QRCodeGenerateBean extends BaseBean {
|
||||
|
||||
private String url;
|
||||
private String qrcode_key;
|
||||
|
||||
}
|
||||
288
src/main/java/com/yutou/biliapi/bean/login/UserInfoBean.java
Normal file
288
src/main/java/com/yutou/biliapi/bean/login/UserInfoBean.java
Normal file
@@ -0,0 +1,288 @@
|
||||
package com.yutou.biliapi.bean.login;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.common.okhttp.BaseBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigInteger;
|
||||
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 BigInteger 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.biliapi.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.biliapi.bean.websocket;
|
||||
|
||||
import com.yutou.biliapi.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,52 @@
|
||||
package com.yutou.biliapi.bean.websocket.live;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.common.utils.Log;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* 弹幕信息
|
||||
* <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 BigInteger 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).getBigInteger(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,49 @@
|
||||
package com.yutou.biliapi.bean.websocket.live;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.common.inter.ISqlDatabaseBean;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@Data
|
||||
public class WSData implements Serializable, ISqlDatabaseBean {
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJson(){
|
||||
return jsonSrc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.yutou.biliapi.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.biliapi.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.biliapi.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 long uid;
|
||||
private int type; //1为进场,2为关注
|
||||
private long roomId;
|
||||
private long timer;
|
||||
private String uname;
|
||||
private String uname_color;
|
||||
private String face;
|
||||
private WSUserMedal medal;
|
||||
|
||||
|
||||
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.biliapi.bean.websocket.live;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.yutou.common.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,247 @@
|
||||
package com.yutou.biliapi.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 int 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 int comboNum;
|
||||
@JSONField(name = "gift_id")
|
||||
private long giftID;
|
||||
@JSONField(name = "gift_name")
|
||||
private String giftName;
|
||||
@JSONField(name = "gift_num")
|
||||
private int giftNum;
|
||||
@JSONField(name = "uid")
|
||||
private long uid;
|
||||
@JSONField(name = "uname")
|
||||
private String uname;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.yutou.biliapi.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-super_chat_message">醒目留言</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.biliapi.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,79 @@
|
||||
package com.yutou.biliapi.databases;
|
||||
|
||||
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
|
||||
import com.yutou.biliapi.bean.login.LoginUserDatabaseBean;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import com.yutou.common.databases.SQLiteManager;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public class BiliBiliLoginDatabase extends SQLiteManager {
|
||||
LoginCookieDatabaseBean cookie;
|
||||
private static BiliBiliLoginDatabase instance;
|
||||
|
||||
private BiliBiliLoginDatabase(Class<LoginCookieDatabaseBean> tClass) {
|
||||
try {
|
||||
cookie = new LoginCookieDatabaseBean();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
public static BiliBiliLoginDatabase getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new BiliBiliLoginDatabase(LoginCookieDatabaseBean.class);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
public BiliBiliLoginDatabase initData(LoginCookieDatabaseBean cookie, LoginUserDatabaseBean user) {
|
||||
this.cookie = cookie;
|
||||
cookie.setTableName(getDataBean().get(0).getTableName());
|
||||
add(cookie);
|
||||
add(user);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoginCookieDatabaseBean getCookie(String userId) {
|
||||
List<LoginCookieDatabaseBean> list = super.get(cookie.getTableName(), LoginCookieDatabaseBean.class);
|
||||
if (userId == null && !list.isEmpty()) {
|
||||
return list.getFirst();
|
||||
}
|
||||
for (LoginCookieDatabaseBean bean : list) {
|
||||
if (bean.getSid().equals(userId)) {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public LoginUserDatabaseBean getUser(String userId) {
|
||||
List<LoginUserDatabaseBean> list = super.get(cookie.getTableName(), LoginUserDatabaseBean.class);
|
||||
if (userId == null && !list.isEmpty()) {
|
||||
return list.getFirst();
|
||||
}
|
||||
for (LoginUserDatabaseBean bean : list) {
|
||||
if (bean.getUserInfo().getMid().equals(new BigInteger(userId))) {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return "bilibili_login.db";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbsDatabasesBean> getDataBean() {
|
||||
return List.of(new LoginCookieDatabaseBean(), new LoginUserDatabaseBean(null));
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.yutou.biliapi.databases;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import com.yutou.common.databases.SQLiteManager;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BiliLiveConfigDatabase extends SQLiteManager {
|
||||
String fileName;
|
||||
|
||||
public BiliLiveConfigDatabase() {
|
||||
this.fileName = "live_config.db";
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbsDatabasesBean> getDataBean() {
|
||||
return List.of(new LiveConfigDatabaseBean());
|
||||
}
|
||||
|
||||
public void setConfig(LiveConfigDatabaseBean bean) {
|
||||
LiveConfigDatabaseBean config = getConfig(bean.getRoomId());
|
||||
if (config == null) {
|
||||
add(bean);
|
||||
return;
|
||||
}
|
||||
bean.setSql_time(config.getSql_time());
|
||||
update(bean);
|
||||
}
|
||||
|
||||
public LiveConfigDatabaseBean getConfig(BigInteger roomId) {
|
||||
List<LiveConfigDatabaseBean> list = get(getDataBean().get(0).getTableName(), LiveConfigDatabaseBean.class);
|
||||
if (list.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (LiveConfigDatabaseBean bean : list) {
|
||||
if (bean.getRoomId() == roomId) {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public boolean deleteConfig(BigInteger roomId) {
|
||||
LiveConfigDatabaseBean config = getConfig(roomId);
|
||||
if (config == null) {
|
||||
return false;
|
||||
}
|
||||
return delete(config);
|
||||
}
|
||||
public List<LiveConfigDatabaseBean> getAllConfig() {
|
||||
List<LiveConfigDatabaseBean> list = get(getDataBean().get(0).getTableName(), LiveConfigDatabaseBean.class);
|
||||
if (list.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
121
src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java
Normal file
121
src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java
Normal file
@@ -0,0 +1,121 @@
|
||||
package com.yutou.biliapi.databases;
|
||||
|
||||
import com.alibaba.fastjson2.util.DateUtils;
|
||||
import com.yutou.biliapi.bean.live.*;
|
||||
import com.yutou.biliapi.bean.live.database.*;
|
||||
import com.yutou.biliapi.bean.websocket.live.*;
|
||||
import com.yutou.common.databases.AbsDatabasesBean;
|
||||
import com.yutou.common.databases.SQLiteManager;
|
||||
import com.yutou.common.okhttp.HttpDownloadUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.fastjson2.util.DateUtils.DateTimeFormatPattern.DATE_FORMAT_10_DASH;
|
||||
|
||||
public class BiliLiveDatabase extends SQLiteManager {
|
||||
LiveInfoDatabaseBean bean;
|
||||
LiveRoomConfig config;
|
||||
String fileName;
|
||||
File rootPath;
|
||||
public BiliLiveDatabase(LiveRoomConfig roomConfig) {
|
||||
String time = DateUtils.format(new Date().getTime(), DATE_FORMAT_10_DASH);
|
||||
rootPath = new File(roomConfig.getAnchorName() + File.separator + time + roomConfig.getRoomInfo().getTitle());
|
||||
config=roomConfig;
|
||||
if(!rootPath.exists()){
|
||||
rootPath.mkdirs();
|
||||
}
|
||||
fileName=rootPath.getAbsolutePath()+File.separator+"live.db";
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
super.init();
|
||||
HttpDownloadUtils.download(config.getRoomInfo().getUserCover(),rootPath.getAbsolutePath(),"poster.jpg");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbsDatabasesBean> getDataBean() {
|
||||
return List.of(
|
||||
new LiveInfoDatabaseBean(),
|
||||
new LiveDanmuDatabaseBean(),
|
||||
new LiveGiftDatabaseBean(),
|
||||
new LiveInteractWordDatabaseBean(),
|
||||
new LiveSuperChatDatabaseBean(),
|
||||
new LiveSourceDatabaseBean()
|
||||
);
|
||||
}
|
||||
|
||||
public void addLiveInfo(LiveRoomInfo info) {
|
||||
this.bean = new LiveInfoDatabaseBean(info);
|
||||
|
||||
List<LiveInfoDatabaseBean> infos = get(bean.getTableName(), LiveInfoDatabaseBean.class);
|
||||
if (infos.isEmpty()) {
|
||||
createInfo(bean);
|
||||
}
|
||||
}
|
||||
|
||||
private void addData(WSData bean) {
|
||||
if (bean instanceof WSDanmuData) {
|
||||
add(new LiveDanmuDatabaseBean((WSDanmuData) bean));
|
||||
} else if (bean instanceof WSInteractWord) {
|
||||
add(new LiveInteractWordDatabaseBean((WSInteractWord) bean));
|
||||
} else if (bean instanceof WSSendGift) {
|
||||
add(new LiveGiftDatabaseBean((WSSendGift) bean));
|
||||
} else if (bean instanceof WSSuperChatMessage) {
|
||||
add(new LiveSuperChatDatabaseBean((WSSuperChatMessage) bean));
|
||||
}
|
||||
}
|
||||
|
||||
public void addSource(WSData bean) {
|
||||
add(new LiveSourceDatabaseBean(bean));
|
||||
addData(bean);
|
||||
}
|
||||
|
||||
private void createInfo(LiveInfoDatabaseBean bean) {
|
||||
add(bean);
|
||||
}
|
||||
|
||||
public List<LiveSourceDatabaseBean> getSource(long startTime, long entTime) {
|
||||
return get(startTime, entTime, LiveSourceDatabaseBean.class);
|
||||
}
|
||||
|
||||
public <T extends AbsDatabasesBean> List<T> get(long startTime, long entTime, Class<T> clazz) {
|
||||
String tableName = null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String where = null;
|
||||
if (startTime != -1) {
|
||||
sb.append(" `sql_time` >= ").append(startTime);
|
||||
}
|
||||
if (entTime != -1) {
|
||||
if (!sb.isEmpty()) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
sb.append(" `sql_time` <= ").append(entTime);
|
||||
}
|
||||
if (!sb.isEmpty()) {
|
||||
where = sb.toString();
|
||||
}
|
||||
for (AbsDatabasesBean bean : getDataBean()) {
|
||||
if (bean.getClass() == clazz) {
|
||||
tableName = bean.getTableName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return super.get(tableName, where, clazz);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
/* List<LiveDanmuDatabaseBean> list = getInstance().get(-1, 1727515148800L, LiveDanmuDatabaseBean.class);
|
||||
for (LiveDanmuDatabaseBean bean : list) {
|
||||
System.out.println(bean.getSql_time() + "|" + bean);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
23
src/main/java/com/yutou/biliapi/enums/LiveProtocol.java
Normal file
23
src/main/java/com/yutou/biliapi/enums/LiveProtocol.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.yutou.biliapi.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);
|
||||
}
|
||||
}
|
||||
22
src/main/java/com/yutou/biliapi/enums/LiveVideoCodec.java
Normal file
22
src/main/java/com/yutou/biliapi/enums/LiveVideoCodec.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.yutou.biliapi.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.biliapi.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);
|
||||
}
|
||||
}
|
||||
23
src/main/java/com/yutou/biliapi/enums/LiveVideoFormat.java
Normal file
23
src/main/java/com/yutou/biliapi/enums/LiveVideoFormat.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.yutou.biliapi.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);
|
||||
}
|
||||
}
|
||||
89
src/main/java/com/yutou/biliapi/net/BiliCookieManager.java
Normal file
89
src/main/java/com/yutou/biliapi/net/BiliCookieManager.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package com.yutou.biliapi.net;
|
||||
|
||||
import com.yutou.biliapi.bean.login.CheckCookieBean;
|
||||
import com.yutou.common.inter.IHttpApiCheckCallback;
|
||||
import com.yutou.common.okhttp.HttpCallback;
|
||||
import com.yutou.common.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(null)
|
||||
.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,71 @@
|
||||
package com.yutou.biliapi.net;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.biliapi.api.LiveApi;
|
||||
import com.yutou.biliapi.bean.live.LiveAnchorInfo;
|
||||
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
|
||||
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
|
||||
import com.yutou.common.okhttp.api.BaseApi;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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 LiveApi getApi(String loginUid) {
|
||||
if(StringUtils.hasText(loginUid)) {
|
||||
LoginCookieDatabaseBean cookie = BiliBiliLoginDatabase.getInstance().getCookie(loginUid);
|
||||
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);
|
||||
return createApi(LiveApi.class);
|
||||
}
|
||||
|
||||
public Map<BigInteger, LiveAnchorInfo> getAnchorInfos(String loginUid,List<BigInteger> anchorIds) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("uids", anchorIds);
|
||||
try {
|
||||
String src = getApi(loginUid).getLiveRoomStatus(json).execute().body().getSrc();
|
||||
json = JSONObject.parseObject(src);
|
||||
if (json.getInteger("code") == 0) {
|
||||
Map<BigInteger, LiveAnchorInfo> map = new HashMap<>();
|
||||
JSONObject data = json.getJSONObject("data");
|
||||
for (String key : data.keySet()) {
|
||||
LiveAnchorInfo info = JSONObject.parseObject(data.getString(key), LiveAnchorInfo.class);
|
||||
map.put(new BigInteger(key), info);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
return new HashMap<>();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
126
src/main/java/com/yutou/biliapi/net/BiliLoginNetApiManager.java
Normal file
126
src/main/java/com/yutou/biliapi/net/BiliLoginNetApiManager.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package com.yutou.biliapi.net;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.biliapi.api.LoginApi;
|
||||
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
|
||||
import com.yutou.biliapi.bean.login.LoginInfoBean;
|
||||
import com.yutou.biliapi.bean.login.QRCodeGenerateBean;
|
||||
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
|
||||
import com.yutou.common.okhttp.HttpBody;
|
||||
import com.yutou.common.okhttp.HttpCallback;
|
||||
import com.yutou.common.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(null);
|
||||
}
|
||||
|
||||
public LoginApi getLoginApi(String loginUid) {
|
||||
if (StringUtils.hasText(loginUid)) {
|
||||
LoginCookieDatabaseBean cookie = BiliBiliLoginDatabase.getInstance().getCookie(loginUid);
|
||||
if (cookie != null) {
|
||||
useCookie(JSONObject.parseObject(JSONObject.toJSONString(cookie)));
|
||||
}
|
||||
}
|
||||
return loginApi;
|
||||
}
|
||||
|
||||
public void login(HttpCallback<LoginCookieDatabaseBean> callback) {
|
||||
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<LoginCookieDatabaseBean> 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);
|
||||
LoginCookieDatabaseBean cookie = JSONObject.parseObject(ck.toString(), LoginCookieDatabaseBean.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,42 @@
|
||||
package com.yutou.biliapi.net;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.yutou.biliapi.api.UserApi;
|
||||
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
|
||||
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
|
||||
import com.yutou.common.inter.IHttpApiCheckCallback;
|
||||
import com.yutou.common.okhttp.api.BaseApi;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
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 UserApi getUserApi(LoginCookieDatabaseBean cookie) {
|
||||
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);
|
||||
}
|
||||
return createApi(UserApi.class);
|
||||
}
|
||||
|
||||
}
|
||||
266
src/main/java/com/yutou/biliapi/net/WebSocketManager.java
Normal file
266
src/main/java/com/yutou/biliapi/net/WebSocketManager.java
Normal file
@@ -0,0 +1,266 @@
|
||||
package com.yutou.biliapi.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.alibaba.fastjson2.util.DateUtils;
|
||||
import com.yutou.biliapi.api.LiveApi;
|
||||
import com.yutou.biliapi.bean.live.LiveDanmuInfo;
|
||||
import com.yutou.biliapi.bean.live.LiveRoomConfig;
|
||||
import com.yutou.biliapi.bean.live.LiveRoomInfo;
|
||||
import com.yutou.biliapi.bean.websocket.WebSocketBody;
|
||||
import com.yutou.biliapi.bean.websocket.WebSocketHeader;
|
||||
import com.yutou.biliapi.bean.websocket.live.WSData;
|
||||
import com.yutou.biliapi.databases.BiliBiliLoginDatabase;
|
||||
import com.yutou.biliapi.databases.BiliLiveDatabase;
|
||||
import com.yutou.biliapi.utils.BiliUserUtils;
|
||||
import com.yutou.biliapi.utils.BytesUtils;
|
||||
import com.yutou.common.okhttp.HttpBody;
|
||||
import com.yutou.common.okhttp.HttpCallback;
|
||||
import com.yutou.common.utils.Log;
|
||||
import okhttp3.Headers;
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
import retrofit2.Response;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alibaba.fastjson2.util.DateUtils.DateTimeFormatPattern.DATE_FORMAT_10_DASH;
|
||||
|
||||
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 boolean checkRoom(LiveRoomConfig roomConfig) {
|
||||
return roomMap.containsKey(roomConfig);
|
||||
}
|
||||
|
||||
public void addRoom(LiveRoomConfig roomConfig) {
|
||||
if (checkRoom(roomConfig)) {
|
||||
return;
|
||||
}
|
||||
LiveApi api = BiliLiveNetApiManager.getInstance().getApi(roomConfig.getLoginUid());
|
||||
Response<HttpBody<LiveRoomInfo>> execute = null;
|
||||
try {
|
||||
execute = api.getRoomInfo(roomConfig.getRoomId().toString()).execute();
|
||||
if (execute.isSuccessful()) {
|
||||
roomConfig.setRoomInfo(execute.body() != null ? execute.body().getData() : null);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
api.getLiveRoomDanmuInfo(String.valueOf(roomConfig.getLoginUid())).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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void stopRoom(LiveRoomConfig roomConfig) {
|
||||
if (checkRoom(roomConfig)) {
|
||||
roomMap.get(roomConfig).close();
|
||||
roomMap.remove(roomConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static class WebSocketClientTh extends WebSocketClient {
|
||||
private LiveRoomConfig roomConfig;
|
||||
private HeartbeatTask heartbeatTask;
|
||||
BiliLiveDatabase liveDatabase;
|
||||
|
||||
public WebSocketClientTh(URI serverUri, LiveRoomConfig roomId) {
|
||||
super(serverUri);
|
||||
this.roomConfig = roomId;
|
||||
heartbeatTask = new HeartbeatTask();
|
||||
Brotli4jLoader.ensureAvailability();
|
||||
liveDatabase = new BiliLiveDatabase(roomConfig);
|
||||
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 {
|
||||
|
||||
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()) {
|
||||
WSData parse = WSData.parse(json);
|
||||
liveDatabase.addSource(parse);
|
||||
Log.i("解压:" + parse);
|
||||
}
|
||||
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", new BigInteger(roomConfig.getLoginUid()));
|
||||
|
||||
} else {
|
||||
json.put("uid", 0);
|
||||
}
|
||||
String buvid = BiliUserUtils.getBuvid(BiliBiliLoginDatabase.getInstance().getCookie(roomConfig.getLoginUid()));
|
||||
if (buvid != null) {
|
||||
try {
|
||||
json.put("roomid", roomConfig.getRoomId());
|
||||
json.put("protover", 3);
|
||||
json.put("buvid", buvid);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
32
src/main/java/com/yutou/biliapi/utils/BiliUserUtils.java
Normal file
32
src/main/java/com/yutou/biliapi/utils/BiliUserUtils.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.yutou.biliapi.utils;
|
||||
|
||||
import com.yutou.biliapi.api.UserApi;
|
||||
import com.yutou.biliapi.bean.live.SpiBean;
|
||||
import com.yutou.biliapi.bean.login.LoginCookieDatabaseBean;
|
||||
import com.yutou.biliapi.net.BiliUserNetApiManager;
|
||||
import com.yutou.common.inter.IHttpApiCheckCallback;
|
||||
import com.yutou.common.okhttp.HttpBody;
|
||||
import com.yutou.common.okhttp.HttpCallback;
|
||||
import com.yutou.common.utils.RedisTools;
|
||||
import okhttp3.Headers;
|
||||
import retrofit2.Response;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BiliUserUtils {
|
||||
public static String getBuvid(LoginCookieDatabaseBean cookie) {
|
||||
Response<HttpBody<SpiBean>> execute = null;
|
||||
try {
|
||||
execute = BiliUserNetApiManager.getInstance().getUserApi(cookie).getFingerSpi().execute();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (execute.isSuccessful()) {
|
||||
if (execute.body() != null) {
|
||||
return execute.body().getData().getB_3();
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
41
src/main/java/com/yutou/biliapi/utils/BytesUtils.java
Normal file
41
src/main/java/com/yutou/biliapi/utils/BytesUtils.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.yutou.biliapi.utils;
|
||||
|
||||
import com.yutou.common.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;
|
||||
}
|
||||
}
|
||||
67
src/main/java/com/yutou/biliapi/utils/LiveHeartBeat.java
Normal file
67
src/main/java/com/yutou/biliapi/utils/LiveHeartBeat.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package com.yutou.biliapi.utils;
|
||||
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user