Compare commits
6 Commits
master
...
590c54b777
| Author | SHA1 | Date | |
|---|---|---|---|
| 590c54b777 | |||
| ac7f076721 | |||
| 91fe70c1b8 | |||
| 9521e9d5c8 | |||
| 54ac47c8b4 | |||
| b178010f8f |
103
pom.xml
103
pom.xml
@@ -5,17 +5,18 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>2.4.3</version>
|
<version>3.3.0</version>
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.yutou</groupId>
|
<groupId>com.yutou</groupId>
|
||||||
<artifactId>bilibili</artifactId>
|
<artifactId>bilibili</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
<name>bilibili</name>
|
<name>bilibili</name>
|
||||||
<description>Demo project for Spring Boot</description>
|
<description>Demo project for Spring Boot</description>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>21</java.version>
|
||||||
<kotlin.version>1.6.10</kotlin.version>
|
<kotlin.version>1.7.22</kotlin.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -25,11 +26,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web-services</artifactId>
|
<artifactId>spring-boot-starter-web-services</artifactId>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -52,9 +48,9 @@
|
|||||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson2</artifactId>
|
||||||
<version>1.2.80</version>
|
<version>2.0.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.xerial</groupId>
|
<groupId>org.xerial</groupId>
|
||||||
@@ -64,23 +60,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.18.22</version>
|
<scope>annotationProcessor</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.java-websocket</groupId>
|
<groupId>org.java-websocket</groupId>
|
||||||
<artifactId>Java-WebSocket</artifactId>
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
<version>1.5.2</version>
|
<version>1.5.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mybatis.spring.boot</groupId>
|
|
||||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
|
||||||
<version>2.2.2</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
@@ -103,30 +89,42 @@
|
|||||||
<version>4.1.2</version>
|
<version>4.1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.mamoe</groupId>
|
|
||||||
<artifactId>mirai-core-jvm</artifactId>
|
|
||||||
<version>2.10.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlinx</groupId>
|
|
||||||
<artifactId>kotlinx-coroutines-jdk8</artifactId>
|
|
||||||
<version>1.6.0-native-mt</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlinx</groupId>
|
|
||||||
<artifactId>kotlinx-coroutines-core-jvm</artifactId>
|
|
||||||
<version>1.6.0-native-mt</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
|
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>redis.clients</groupId>
|
<groupId>redis.clients</groupId>
|
||||||
<artifactId>jedis</artifactId>
|
<artifactId>jedis</artifactId>
|
||||||
<version>4.2.0</version>
|
<version>4.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.reactivex.rxjava3</groupId>
|
||||||
|
<artifactId>rxjava</artifactId>
|
||||||
|
<version>3.1.8</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aayushatharva.brotli4j</groupId>
|
||||||
|
<artifactId>brotli4j</artifactId>
|
||||||
|
<version>1.16.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.12.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.retrofit2</groupId>
|
||||||
|
<artifactId>retrofit</artifactId>
|
||||||
|
<version>2.11.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
|
||||||
|
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
|
||||||
|
<outputDirectory>${project.basedir}/target/classes</outputDirectory>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
@@ -147,27 +145,6 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-maven-plugin</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>compile</id>
|
|
||||||
<goals>
|
|
||||||
<goal>compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
|
|
||||||
<execution>
|
|
||||||
<id>test-compile</id>
|
|
||||||
<goals>
|
|
||||||
<goal>test-compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
@@ -175,7 +152,7 @@
|
|||||||
<!--使用-Dloader.path需要在打包的时候增加<layout>ZIP</layout>,不指定的话-Dloader.path不生效-->
|
<!--使用-Dloader.path需要在打包的时候增加<layout>ZIP</layout>,不指定的话-Dloader.path不生效-->
|
||||||
<layout>ZIP</layout>
|
<layout>ZIP</layout>
|
||||||
<!-- 指定该jar包启动时的主类[建议] -->
|
<!-- 指定该jar包启动时的主类[建议] -->
|
||||||
<mainClass>com.yutou.bilibili.BilibiliApplication</mainClass>
|
<mainClass>com.yutou.BilibiliApplication</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -190,6 +167,14 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>21</source>
|
||||||
|
<target>21</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
|
|||||||
17
src/main/java/com/yutou/BilibiliApplication.java
Normal file
17
src/main/java/com/yutou/BilibiliApplication.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package com.yutou;
|
||||||
|
|
||||||
|
import com.yutou.common.okhttp.HttpLoggingInterceptor;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication()
|
||||||
|
public class BilibiliApplication {
|
||||||
|
|
||||||
|
public static String version = "0.8.4";
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
HttpLoggingInterceptor.setLog(false);
|
||||||
|
SpringApplication.run(BilibiliApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
169
src/main/java/com/yutou/biliapi/Main.java
Normal file
169
src/main/java/com/yutou/biliapi/Main.java
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
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;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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,57 @@
|
|||||||
|
package com.yutou.biliapi.bean.live;
|
||||||
|
|
||||||
|
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
|
||||||
|
import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LiveRoomConfig {
|
||||||
|
String loginUid;
|
||||||
|
BigInteger roomId;
|
||||||
|
String anchorName;
|
||||||
|
boolean isLogin;
|
||||||
|
String rootPath="live";
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LiveRoomConfig buildConfig(String roomId){
|
||||||
|
BiliLiveConfigDatabase database = new BiliLiveConfigDatabase();
|
||||||
|
LiveConfigDatabaseBean bean = database.getConfig(new BigInteger(roomId));
|
||||||
|
|
||||||
|
LiveRoomConfig config = new LiveRoomConfig();
|
||||||
|
config.setLoginUid(bean.getRecordUid());
|
||||||
|
config.setRoomId(bean.getRoomId());
|
||||||
|
config.setAnchorName(bean.getAnchorName());
|
||||||
|
config.setLogin(StringUtils.hasText(bean.getRecordUid()));
|
||||||
|
config.setRootPath(bean.getRecordPath());
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
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,81 @@
|
|||||||
|
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 = "recordPath")
|
||||||
|
private String recordPath="live";
|
||||||
|
@JSONField(name = "recordUid")
|
||||||
|
private String recordUid;
|
||||||
|
@JSONField(name = "recordLiveModel")
|
||||||
|
private int recordLiveModel;//0 - ffmpeg 1 - java
|
||||||
|
@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,58 @@
|
|||||||
|
package com.yutou.biliapi.bean.live.database;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import com.yutou.biliapi.bean.websocket.live.WSDanmuData;
|
||||||
|
import com.yutou.bilibili.datas.DanmuData;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DanmuData createDanmuData() {
|
||||||
|
DanmuData data = new DanmuData();
|
||||||
|
data.setId(id);
|
||||||
|
data.setDanmu(danmu);
|
||||||
|
data.setModel(model);
|
||||||
|
data.setFontSize(fontSize);
|
||||||
|
data.setFontColor(fontColor);
|
||||||
|
data.setTime(time);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,23 @@
|
|||||||
|
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.util.Date;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class LiveVideoDatabaseBean extends AbsDatabasesBean {
|
||||||
|
@JSONField(name = "info")
|
||||||
|
String roomInfoJson;
|
||||||
|
@JSONField(name = "start_time")
|
||||||
|
Date startTime;
|
||||||
|
@JSONField(name = "path")
|
||||||
|
String path;
|
||||||
|
|
||||||
|
public LiveVideoDatabaseBean() {
|
||||||
|
super("live_video", System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,38 @@
|
|||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toCookieString() {
|
||||||
|
return "SESSDATA=" + sessdta + "; Path=" + path + "; DedeUserID=" + dedeUserID + "; DedeUserID__ckMd5=" + dedeUserIDCkMd5 + "; bili_jct=" + biliJct + "; Expires=" + expires + "; Domain=" + domain + "; sid=" + sid + "; gourl=" + gourl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.getDedeUserID().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 "old_bilibili_login.db";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<AbsDatabasesBean> getDataBean() {
|
||||||
|
return List.of(new LoginCookieDatabaseBean(), new LoginUserDatabaseBean(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.yutou.biliapi.databases;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.biliapi.bean.live.LiveRoomConfig;
|
||||||
|
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
|
||||||
|
import com.yutou.common.databases.AbsDatabasesBean;
|
||||||
|
import com.yutou.common.databases.SQLiteManager;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
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 (Objects.equals(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
143
src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java
Normal file
143
src/main/java/com/yutou/biliapi/databases/BiliLiveDatabase.java
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
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.bilibili.Tools.DateFormatUtils;
|
||||||
|
import com.yutou.common.databases.AbsDatabasesBean;
|
||||||
|
import com.yutou.common.databases.SQLiteManager;
|
||||||
|
import com.yutou.common.okhttp.HttpDownloadUtils;
|
||||||
|
import org.apache.poi.ss.usermodel.DataFormat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
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 {
|
||||||
|
LiveRoomConfig config;
|
||||||
|
String fileName;
|
||||||
|
File rootPath;
|
||||||
|
|
||||||
|
public BiliLiveDatabase(LiveRoomConfig roomConfig, String path) {
|
||||||
|
this.config = roomConfig;
|
||||||
|
rootPath = new File(path).getParentFile();
|
||||||
|
fileName =path;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BiliLiveDatabase(LiveRoomConfig roomConfig) {
|
||||||
|
String time = DateUtils.format(new Date().getTime(), DATE_FORMAT_10_DASH);
|
||||||
|
rootPath = new File(roomConfig.getRootPath() + File.separator + roomConfig.getAnchorName() + File.separator + time + File.separator + roomConfig.getRoomInfo().getTitle());
|
||||||
|
config = roomConfig;
|
||||||
|
if (!rootPath.exists()) {
|
||||||
|
rootPath.mkdirs();
|
||||||
|
}
|
||||||
|
fileName = rootPath.getAbsolutePath() + File.separator + "live.db";
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
super.init();
|
||||||
|
if(config.getRoomInfo()!=null) {
|
||||||
|
HttpDownloadUtils.download(new HttpDownloadUtils.Builder().setUrl(config.getRoomInfo().getUserCover())
|
||||||
|
.setPath(rootPath.getAbsolutePath())
|
||||||
|
.setFileName("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(),
|
||||||
|
new LiveVideoDatabaseBean()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLiveInfo(LiveVideoDatabaseBean info) {
|
||||||
|
createInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LiveVideoDatabaseBean> getLiveInfos() {
|
||||||
|
return get(new LiveVideoDatabaseBean().getTableName(), LiveVideoDatabaseBean.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
System.out.println("BiliLiveDatabase.addSource");
|
||||||
|
add(new LiveSourceDatabaseBean(bean));
|
||||||
|
addData(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createInfo(LiveVideoDatabaseBean bean) {
|
||||||
|
String format = DateFormatUtils.format(bean.getSql_time());
|
||||||
|
if (get(bean.getTableName(), " `sql_time` = '" + format + "'", LiveVideoDatabaseBean.class).isEmpty()) {
|
||||||
|
add(bean);
|
||||||
|
} else {
|
||||||
|
update(bean);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends AbsDatabasesBean> List<T> getOfTime(String startTime, String entTime, Class<T> clazz) {
|
||||||
|
String tableName = null;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String where = null;
|
||||||
|
if (startTime != null) {
|
||||||
|
sb.append(" `sql_time` >= ").append("\"").append(startTime).append("\"");
|
||||||
|
}
|
||||||
|
if (entTime != null) {
|
||||||
|
if (!sb.isEmpty()) {
|
||||||
|
sb.append(" and ");
|
||||||
|
}
|
||||||
|
sb.append(" `sql_time` <= ").append("\"").append(entTime).append("\"");
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
308
src/main/java/com/yutou/biliapi/net/WebSocketManager.java
Normal file
308
src/main/java/com/yutou/biliapi/net/WebSocketManager.java
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
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.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
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.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 java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class WebSocketManager {
|
||||||
|
ThreadPoolExecutor executor;
|
||||||
|
private static WebSocketManager instance;
|
||||||
|
Map<LiveRoomConfig, DanmuTask> roomMap;
|
||||||
|
private final List<String> userStopList = new ArrayList<>();//手动停止列表
|
||||||
|
|
||||||
|
private WebSocketManager() {
|
||||||
|
roomMap = new HashMap<>();
|
||||||
|
executor = new ThreadPoolExecutor(2, 4, Long.MAX_VALUE, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebSocketManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new WebSocketManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkRoom(LiveRoomConfig roomConfig) {
|
||||||
|
return roomMap.containsKey(roomConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONArray getLiveRoomList() {
|
||||||
|
JSONArray array = new JSONArray();
|
||||||
|
array.addAll(roomMap.keySet());
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRoom(LiveRoomConfig roomConfig, boolean isUser) {
|
||||||
|
if (!isUser && userStopList.contains(roomConfig.getRoomId().toString())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (checkRoom(roomConfig)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isUser) {
|
||||||
|
userStopList.remove(roomConfig.getRoomId().toString());
|
||||||
|
}
|
||||||
|
DanmuTask task = new DanmuTask(roomConfig);
|
||||||
|
roomMap.put(roomConfig, task);
|
||||||
|
System.out.println("添加websocket任务");
|
||||||
|
executor.execute(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopRoom(String roomId, boolean isUser) {
|
||||||
|
LiveRoomConfig roomConfig=new LiveRoomConfig();
|
||||||
|
roomConfig.setRoomId(new BigInteger(roomId));
|
||||||
|
if (checkRoom(roomConfig)) {
|
||||||
|
roomMap.get(roomConfig).close();
|
||||||
|
roomMap.remove(roomConfig);
|
||||||
|
}
|
||||||
|
if (isUser) {
|
||||||
|
userStopList.add(roomConfig.getRoomId().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DanmuTask implements Runnable {
|
||||||
|
LiveRoomConfig roomConfig;
|
||||||
|
WebSocketClientTh client;
|
||||||
|
|
||||||
|
public DanmuTask(LiveRoomConfig config) {
|
||||||
|
this.roomConfig = config;
|
||||||
|
WebSocketManager.getInstance().roomMap.put(roomConfig, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
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.getRoomId())).enqueue(new HttpCallback<LiveDanmuInfo>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Headers headers, int code, String status, LiveDanmuInfo response, String rawResponse) {
|
||||||
|
if (!response.getHostList().isEmpty()) {
|
||||||
|
LiveDanmuInfo.Host host = response.getHostList().get(0);
|
||||||
|
String url = "wss://" + host.getHost() + ":" + host.getWssPort() + "/sub";
|
||||||
|
// url="ws://127.0.0.1:8765";
|
||||||
|
try {
|
||||||
|
roomConfig.setLiveInfo(response);
|
||||||
|
client = new WebSocketClientTh(new URI(url), roomConfig);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
throwable.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class WebSocketClientTh extends WebSocketClient {
|
||||||
|
private LiveRoomConfig roomConfig;
|
||||||
|
private HeartbeatTask heartbeatTask;
|
||||||
|
BiliLiveDatabase liveDatabase;
|
||||||
|
private boolean itTmp = true;
|
||||||
|
|
||||||
|
public WebSocketClientTh(URI serverUri, LiveRoomConfig roomId) {
|
||||||
|
super(serverUri);
|
||||||
|
System.out.println("WebSocketClientTh.WebSocketClientTh : " + serverUri);
|
||||||
|
this.roomConfig = roomId;
|
||||||
|
liveDatabase = new BiliLiveDatabase(roomConfig);
|
||||||
|
Brotli4jLoader.ensureAvailability();
|
||||||
|
heartbeatTask = new HeartbeatTask();
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen(ServerHandshake serverHandshake) {
|
||||||
|
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: " + roomConfig.getAnchorName());
|
||||||
|
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("协议:" + 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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Controllers;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/bili/")
|
|
||||||
public class BiliUserController {
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/login/get/test.do")
|
|
||||||
public JSONObject testLogin(){
|
|
||||||
JSONObject json=new JSONObject();
|
|
||||||
if(StringUtils.isEmpty(AppTools.readFile(new File("cookies.json")))){
|
|
||||||
json.put("code",-1);
|
|
||||||
json.put("msg","未登录");
|
|
||||||
}else{
|
|
||||||
JSONObject login= LiveUtils.getUserLoginInfo();
|
|
||||||
JSONObject data=new JSONObject();
|
|
||||||
json.put("code",login.getInteger("code"));
|
|
||||||
data.put("uname",login.getJSONObject("data").getString("uname"));
|
|
||||||
data.put("icon",login.getJSONObject("data").getString("face"));
|
|
||||||
json.put("data",data);
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/login/set/login.do")
|
|
||||||
public JSONObject login(){
|
|
||||||
JSONObject login=LiveUtils.http_get("https://passport.bilibili.com/qrcode/getLoginUrl");
|
|
||||||
JSONObject json=new JSONObject();
|
|
||||||
json.put("code",login.getInteger("code"));
|
|
||||||
json.put("url",login.getJSONObject("data").getString("url"));
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
waitLogin(login.getJSONObject("data").getString("oauthKey"));
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
public void waitLogin(String oauthKey){
|
|
||||||
long time=System.currentTimeMillis();
|
|
||||||
String bd="gourl=https%3A%2F%2Fpassport.bilibili.com%2Fajax%2FminiLogin%2Fredirect&oauthKey="+oauthKey;
|
|
||||||
new Timer().schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if((System.currentTimeMillis()-time)>5*60*1000){
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JSONObject json=LiveUtils.http_post("https://passport.bilibili.com/qrcode/getLoginInfo",bd);
|
|
||||||
if(json.containsKey("code")&&json.getInteger("code")==0){
|
|
||||||
String _url=json.getJSONObject("data").getString("url");
|
|
||||||
Map<String,String> map=AppTools.getUrlParams(_url);
|
|
||||||
JSONObject tmp=LiveUtils.http_post(_url,"");
|
|
||||||
JSONObject cookie=new JSONObject();
|
|
||||||
for (String key : map.keySet()) {
|
|
||||||
cookie.put(key,map.get(key));
|
|
||||||
}
|
|
||||||
String sid=tmp.getString("cookie");
|
|
||||||
sid=sid.split("sid=")[1];
|
|
||||||
sid=sid.split(";")[0];
|
|
||||||
cookie.put("sid",sid);
|
|
||||||
cookie.put("Domain",".bilibili.com");
|
|
||||||
AppTools.saveFile(new File("cookies.json"),cookie.toJSONString());
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},0,3000);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Controllers;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.BiliTools;
|
|
||||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
|
||||||
import com.yutou.bilibili.Services.IUserService;
|
|
||||||
import com.yutou.bilibili.Tools.*;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUser;
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class BiliVideoController {
|
|
||||||
@Resource
|
|
||||||
IUserService service;
|
|
||||||
@Resource
|
|
||||||
IBiliBiliLiveService liveService;
|
|
||||||
@Resource
|
|
||||||
ISystemConfigService configService;
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/bili/video/get/list.do")
|
|
||||||
public JSONObject videoList(HttpServletRequest request) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
String token = AppTools.getLoginToken(request);
|
|
||||||
UUser user = service.getUserToToken(token);
|
|
||||||
if (user == null) {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "未登录");
|
|
||||||
json.put("data", new JSONObject());
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
if (ServiceTools.getInstance().auth(request, user.getUser(), "/bili/video/get/")) {
|
|
||||||
File file = new File(ConfigTools.load(ConfigTools.CONFIG,"liveSavePath",String.class));
|
|
||||||
Log.i(file.getAbsolutePath());
|
|
||||||
if (!file.exists() || Objects.requireNonNull(file.listFiles()).length == 0) {
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "文件夹为空");
|
|
||||||
json.put("data", new JSONObject());
|
|
||||||
} else {
|
|
||||||
List<File> list = AppTools.scanFilePath(file.getAbsolutePath()+File.separator+"live");
|
|
||||||
JSONArray array = new JSONArray();
|
|
||||||
for (File f : list) {
|
|
||||||
if(!f.getName().endsWith(".mp4")){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
JSONObject item = new JSONObject();
|
|
||||||
String _time = f.getName().split(" ")[0].substring(1);
|
|
||||||
File mpeg = new File("ffmpeg_out" + File.separator + _time + File.separator + f.getName());
|
|
||||||
if (mpeg.exists()) {
|
|
||||||
f = mpeg;
|
|
||||||
item.put("ffmpeg", true);
|
|
||||||
} else {
|
|
||||||
item.put("ffmpeg", false);
|
|
||||||
}
|
|
||||||
String date = f.getName().split(" ")[0].substring(1);
|
|
||||||
String time = f.getName().split(" ")[1].split("\\]")[0];
|
|
||||||
String roomid = f.getName().split("\\]")[1].replace(".mp4", "").replace("_ffmpeg", "").trim();
|
|
||||||
|
|
||||||
BilibiliUpInfo info = liveService.queryUpToRoomId(Integer.parseInt(roomid));
|
|
||||||
long size = f.length();
|
|
||||||
String _size;
|
|
||||||
if (size < 1024) {
|
|
||||||
_size = size + "B";
|
|
||||||
} else if (size < 1048576) {
|
|
||||||
_size = (size / 1024) + "KB";
|
|
||||||
} else if (size < 1073741824) {
|
|
||||||
_size = (size / 1048576) + "MB";
|
|
||||||
} else {
|
|
||||||
_size = (size / 1073741824) + "GB";
|
|
||||||
}
|
|
||||||
|
|
||||||
item.put("fileName", f.getName());
|
|
||||||
item.put("fileSize", _size);
|
|
||||||
item.put("date", date);
|
|
||||||
item.put("time", time);
|
|
||||||
item.put("name", info == null ? roomid : info.getName());
|
|
||||||
array.add(item);
|
|
||||||
}
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "ok");
|
|
||||||
json.put("data", array);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
json.put("code", -2);
|
|
||||||
json.put("msg", "未授权");
|
|
||||||
json.put("data", new JSONObject());
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/bili/video/download/get.do")
|
|
||||||
public ResponseEntity<FileSystemResource> download(String fileName) {
|
|
||||||
String time = fileName.split(" ")[0].substring(1);
|
|
||||||
File file = new File("ffmpeg_out" + File.separator + time + File.separator + fileName);
|
|
||||||
if (!file.exists()) {
|
|
||||||
file = new File(ConfigTools.load(ConfigTools.CONFIG,"liveSavePath",String.class)+File.separator+"live" + File.separator + time + File.separator + fileName);
|
|
||||||
}
|
|
||||||
Log.i(file.getAbsolutePath());
|
|
||||||
return AppTools.getFile(file);
|
|
||||||
}
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/bili/video/set/ffmpeg.do")
|
|
||||||
public JSONObject ffmpegOut(String fileName) throws UnsupportedEncodingException {
|
|
||||||
fileName= URLDecoder.decode(fileName,"UTF-8");
|
|
||||||
JSONObject json=new JSONObject();
|
|
||||||
json.put("code",0);
|
|
||||||
json.put("msg","ok");
|
|
||||||
String time = fileName.split(" ")[0].substring(1);
|
|
||||||
File file = new File("live" + File.separator + time + File.separator + fileName);
|
|
||||||
System.out.println("file "+file.getAbsolutePath()+" "+file.exists());
|
|
||||||
String ffmpeg=configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG);
|
|
||||||
if(StringUtils.isEmpty(ffmpeg)||!new File(ffmpeg).exists()){
|
|
||||||
json.put("msg","FFmpeg未设置,请联系管理员");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
int i= FFmpegUtils.add(configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG),file,new File("ffmpeg_out"+File.separator+time));
|
|
||||||
json.put("model",i);
|
|
||||||
switch (i){
|
|
||||||
case 0:
|
|
||||||
json.put("msg","已添加到后台转码");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
json.put("msg","已经转码,无须二次转码");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
json.put("msg","正在转码");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Controllers;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.LiveData;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.Tools.ExcelUtils;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveData;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.File;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class OverviewController {
|
|
||||||
@Resource
|
|
||||||
IBiliBiliLiveService manager;
|
|
||||||
|
|
||||||
@RequestMapping("/overview/get/query.do")
|
|
||||||
@ResponseBody
|
|
||||||
public JSONObject queryOverview(Date startTime, Date endTime, BilibiliUpInfo upData) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
//BiliBiliLiveDatabasesManager manager = BiliBiliLiveDatabasesManager.getInstance();
|
|
||||||
data.put("giftCount", manager.queryGiftSize(upData.getRoomid(), -1, startTime, endTime));
|
|
||||||
data.put("giftUserCount", manager.queryGiftUserToDistinct(upData, startTime, endTime, new String[]{
|
|
||||||
LiveData.SEND_GIFT
|
|
||||||
, LiveData.COMBO_SEND
|
|
||||||
, LiveData.GUARD_BUY}));
|
|
||||||
data.put("price", manager.queryPriceSize(upData.getRoomid(), startTime, endTime));
|
|
||||||
long h = (endTime.getTime() - startTime.getTime()) % (1000 * 24 * 60 * 60) / (1000 * 60 * 60);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("相差:" + h + "小时");
|
|
||||||
try {
|
|
||||||
data.put("hprice", data.getInteger("price") / h);
|
|
||||||
} catch (Exception e) {
|
|
||||||
data.put("hprice", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
JSONArray array=new JSONArray();
|
|
||||||
List<BilibiliLiveInfo> infos=manager.queryLiveInfo(upData,startTime,endTime);
|
|
||||||
int maxUser=0;
|
|
||||||
for (BilibiliLiveInfo info : infos) {
|
|
||||||
com.yutou.bilibili.Tools.Log.i(info);
|
|
||||||
maxUser+=info.getUserindex()+info.getVipuserindex();
|
|
||||||
JSONObject item=new JSONObject();
|
|
||||||
String nowTime = new SimpleDateFormat("HH").format(info.getSubtime());
|
|
||||||
item.put("time",nowTime);
|
|
||||||
item.put("popular",info.getPopular());
|
|
||||||
item.put("user",info.getUserindex()+info.getVipuserindex());
|
|
||||||
array.add(item);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Map<String, Integer> map = manager.queryUserGiftCount(upData, startTime, endTime);
|
|
||||||
int huserGift = 0;
|
|
||||||
for (String s : map.keySet()) {
|
|
||||||
huserGift += map.get(s);
|
|
||||||
}
|
|
||||||
data.put("userGift", huserGift / maxUser);
|
|
||||||
} catch (Exception e) {
|
|
||||||
data.put("userGift", 0);
|
|
||||||
}
|
|
||||||
data.put("map",array);
|
|
||||||
json.put("data",data);
|
|
||||||
json.put("code",0);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/overview/get/down.do")
|
|
||||||
public JSONObject downExcel(Date startTime, Date endTime, BilibiliUpInfo upData){
|
|
||||||
final String fileName=System.currentTimeMillis()+".xlsx";
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ExcelUtils.getInstance(upData.getRoomid(),startTime,endTime,fileName);
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
JSONObject json=new JSONObject();
|
|
||||||
json.put("code",0);
|
|
||||||
json.put("data",fileName);
|
|
||||||
return json;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/overview/get/download.do")
|
|
||||||
public ResponseEntity<FileSystemResource> downloadExcel(HttpServletRequest request, String fname){
|
|
||||||
File file=new File("excel"+File.separator+fname);
|
|
||||||
if(file.exists()) {
|
|
||||||
return AppTools.getFile(file);
|
|
||||||
}else{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Controllers;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.LiveData;
|
|
||||||
import com.yutou.bilibili.BiliBili.Live;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.Tools.Log;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveData;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/realTimeData/")
|
|
||||||
public class RealTimeDataController {
|
|
||||||
@Resource
|
|
||||||
IBiliBiliLiveService service;
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("get/query.do")
|
|
||||||
public JSONObject queryToDayLiveData(int roomid,Date startTime,Date endTime){
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
BilibiliUpInfo info = new BilibiliUpInfo();
|
|
||||||
info.setRoomid(roomid);
|
|
||||||
Live live = LiveUtils.liveContains(info);
|
|
||||||
if(startTime==null){
|
|
||||||
startTime=AppTools.getToDayStartTime();
|
|
||||||
}
|
|
||||||
if(endTime==null){
|
|
||||||
endTime=AppTools.getToDayNowTime();
|
|
||||||
}
|
|
||||||
int userCount = service.queryLiveData(info.getRoomid(), startTime, endTime, new String[]{LiveData.INTERACT_WORD}).size();
|
|
||||||
int vipCount = service.queryLiveData(info.getRoomid(), startTime, endTime, new String[]{LiveData.ENTRY_EFFECT}).size();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
data.put("roomid", roomid);
|
|
||||||
data.put("popular",live==null?0:live.getInfo().getPopular());
|
|
||||||
data.put("userLength", userCount);
|
|
||||||
data.put("vipLength", vipCount);
|
|
||||||
|
|
||||||
JSONArray price = new JSONArray();
|
|
||||||
//改写这个sql可以按时段统计数据
|
|
||||||
List<Map<String, BigDecimal>> ps=service.queryTimeGroup(roomid, startTime, endTime);
|
|
||||||
for (Map<String, BigDecimal> map : ps) {
|
|
||||||
JSONObject pr = new JSONObject();
|
|
||||||
pr.put("price", map.containsKey("price") ? map.get("price") : 0);
|
|
||||||
pr.put("time", map.get("time"));
|
|
||||||
price.add(pr);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONArray giftArray = new JSONArray();
|
|
||||||
Map<String, Integer> map = service.queryGiftSize(roomid,startTime,endTime);
|
|
||||||
for (String key : map.keySet()) {
|
|
||||||
JSONObject item = new JSONObject();
|
|
||||||
if(key==null|| "null".equals(key)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
item.put("giftName",key);
|
|
||||||
item.put("size",map.get(key));
|
|
||||||
giftArray.add(item);
|
|
||||||
}
|
|
||||||
data.put("price", price);
|
|
||||||
data.put("gift", giftArray);
|
|
||||||
json.put("data", data);
|
|
||||||
json.put("code",0);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("data.do")
|
|
||||||
public JSONObject queryRoomData(int rid,int model){
|
|
||||||
Date startTime = AppTools.getToDayStartTime();
|
|
||||||
Date endTime=AppTools.getToDayNowTime();
|
|
||||||
List<BilibiliLiveData> giftList = service.queryLiveData(rid, startTime, endTime, new String[]{
|
|
||||||
LiveData.SEND_GIFT
|
|
||||||
, LiveData.COMBO_SEND
|
|
||||||
, LiveData.GUARD_BUY
|
|
||||||
});
|
|
||||||
List<BilibiliLiveData> userList = service.queryLiveData(rid, startTime, endTime, new String[]{
|
|
||||||
LiveData.INTERACT_WORD
|
|
||||||
, LiveData.ENTRY_EFFECT
|
|
||||||
});
|
|
||||||
JSONObject json=new JSONObject();
|
|
||||||
JSONArray retData=new JSONArray();
|
|
||||||
if(model==1) {
|
|
||||||
for (BilibiliLiveData data : giftList) {
|
|
||||||
JSONObject item = new JSONObject();
|
|
||||||
item.put("uid", data.getUid());
|
|
||||||
item.put("msg", data.getMsg());
|
|
||||||
json.put("size", data.getGiftindex());
|
|
||||||
json.put("money", data.getPrice());
|
|
||||||
item.put("time", AppTools.getToDayTimeToString(data.getSubtime()));
|
|
||||||
retData.add(item);
|
|
||||||
}
|
|
||||||
}else if(model==2) {
|
|
||||||
for (BilibiliLiveData data : userList) {
|
|
||||||
JSONObject item = new JSONObject();
|
|
||||||
item.put("uid", data.getUid());
|
|
||||||
item.put("msg", data.getMsg());
|
|
||||||
item.put("time", AppTools.getToDayTimeToString(data.getSubtime()));
|
|
||||||
retData.add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
json.put("code",0);
|
|
||||||
json.put("count",retData.size());
|
|
||||||
json.put("data",retData);
|
|
||||||
json.put("msg","");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Controllers;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Live;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveController;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.BiliTools;
|
|
||||||
import com.yutou.bilibili.Services.IUserService;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUser;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class UpInfoController {
|
|
||||||
@Resource
|
|
||||||
IBiliBiliLiveService service;
|
|
||||||
@Resource
|
|
||||||
IUserService userService;
|
|
||||||
|
|
||||||
@RequestMapping("/upinfo/get/list.do")
|
|
||||||
@ResponseBody
|
|
||||||
public JSONObject upInfoList(HttpServletRequest request) {
|
|
||||||
String token = AppTools.getLoginToken(request);
|
|
||||||
UUser user = userService.getUserToToken(token);
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
if (user == null) {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "未登录");
|
|
||||||
json.put("data", "[]");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
List<BilibiliUpInfo> upDataList = service.getUpInfo(user.getId(), user.getPower());
|
|
||||||
com.yutou.bilibili.Tools.Log.i("UP用户数:" + upDataList.size());
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("data", JSONArray.toJSON(upDataList));
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/upinfo/set/add.do")
|
|
||||||
public JSONObject addUpInfo(BilibiliUpInfo upData) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
if (BiliTools.checkout(upData) != null) {
|
|
||||||
upData.setEnable(0);
|
|
||||||
upData = BiliTools.checkout(upData);
|
|
||||||
com.yutou.bilibili.Tools.Log.i(upData);
|
|
||||||
boolean flag = service.addUpInfo(upData);
|
|
||||||
if (flag) {
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "添加成功");
|
|
||||||
} else {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "添加失败,该UP已经存在");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
json.put("code", -2);
|
|
||||||
json.put("msg", "添加失败,可能参数有问题或该UP已经存在");
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/upinfo/update.do")
|
|
||||||
public JSONObject updateV1(BilibiliUpInfo upData) {
|
|
||||||
return update(upData);
|
|
||||||
}
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/upinfo/set/update.do")
|
|
||||||
public JSONObject update(BilibiliUpInfo upData) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("old data =" + upData);
|
|
||||||
BilibiliUpInfo old = service.queryUp(upData);
|
|
||||||
if (!old.getUrl().equals(upData.getUrl())) {
|
|
||||||
upData = BiliTools.checkout(upData);
|
|
||||||
if (upData != null) {
|
|
||||||
upData.setEnable(0);
|
|
||||||
upData.setSavedanmu(0);
|
|
||||||
upData.setOfflinelistening(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
com.yutou.bilibili.Tools.Log.i("save data = " + upData);
|
|
||||||
boolean flag = service.updateUpInfo(upData);
|
|
||||||
if (flag) {
|
|
||||||
LiveController.getInstance().updateUpInfo(upData);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "更新成功");
|
|
||||||
} else {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "更新失败,可能参数有问题");
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/upinfo/set/delete.do")
|
|
||||||
public JSONObject delete(BilibiliUpInfo upData) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
com.yutou.bilibili.Tools.Log.i(upData);
|
|
||||||
boolean flag = service.deleteUp(upData);
|
|
||||||
if (flag) {
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "删除成功");
|
|
||||||
} else {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "删除失败,可能参数有问题");
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/upinfo/get/query.do")
|
|
||||||
public JSONObject query(BilibiliUpInfo upData) {
|
|
||||||
upData = service.queryUp(upData);
|
|
||||||
return (JSONObject) JSON.toJSON(upData);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/upinfo/get/liveInfo.do")
|
|
||||||
public JSONObject liveInfo() {
|
|
||||||
List<BilibiliUpInfo> list = service.getUpInfo();
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
JSONArray info = new JSONArray();
|
|
||||||
JSONArray liveArray = new JSONArray();
|
|
||||||
int online = 0;
|
|
||||||
JSONObject infoByUid = LiveUtils.getStatusInfoByUid(list);
|
|
||||||
JSONObject infoData = infoByUid.getJSONObject("data");
|
|
||||||
for (BilibiliUpInfo up : list) {
|
|
||||||
JSONObject user = infoData.getJSONObject(up.getMid() + "");
|
|
||||||
if(user==null){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
up.setLive(user.getInteger("live_status"));
|
|
||||||
if (up.checkLiveStatus() == 1) {
|
|
||||||
online++;
|
|
||||||
}
|
|
||||||
JSONObject item= (JSONObject) JSON.toJSON(up);
|
|
||||||
item.put("listen",Live.lives.get(up.getRoomid())!=null);
|
|
||||||
info.add(JSON.toJSON(item));
|
|
||||||
}
|
|
||||||
for (Live live : Live.lives.values()) {
|
|
||||||
if (live.geData().getLive() == 1) {
|
|
||||||
liveArray.add(JSON.toJSON(live.geData()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.put("online", online);
|
|
||||||
data.put("info", info);
|
|
||||||
data.put("live", liveArray);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("data", data);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Datas;
|
|
||||||
|
|
||||||
public class AppData {
|
|
||||||
public static String FFMPEG="";
|
|
||||||
public static String BILIBILI_HEADERS = "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36 Referer:https://live.bilibili.com";
|
|
||||||
public static boolean LIVE_SAVE_FFMPEG=false;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Datas;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class BiliBiliUpData {
|
|
||||||
int id;
|
|
||||||
String name;
|
|
||||||
String url;
|
|
||||||
int roomId;
|
|
||||||
boolean offlineListening;
|
|
||||||
boolean enable;
|
|
||||||
boolean saveDanmu;
|
|
||||||
|
|
||||||
public void setOfflineListening(int offlineListening) {
|
|
||||||
this.offlineListening = offlineListening==1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnable(int enable) {
|
|
||||||
this.enable = enable==1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSaveDanmu(int saveDanmu) {
|
|
||||||
this.saveDanmu = saveDanmu==1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Datas;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class GiftData {
|
|
||||||
int id;
|
|
||||||
int price;
|
|
||||||
String name;
|
|
||||||
String desc;
|
|
||||||
String rights;
|
|
||||||
String icon;
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Datas;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class LiveData {
|
|
||||||
public static final String INTERACT_WORD="INTERACT_WORD";//普通用户进直播间
|
|
||||||
public static final String ENTRY_EFFECT="ENTRY_EFFECT";//舰长进直播间
|
|
||||||
public static final String DANMU_MSG="DANMU_MSG";//普通弹幕
|
|
||||||
public static final String SEND_GIFT="SEND_GIFT";//送礼
|
|
||||||
public static final String COMBO_SEND="COMBO_SEND";//礼物连击
|
|
||||||
public static final String SUPER_CHAT_MESSAGE="SUPER_CHAT_MESSAGE";//SC
|
|
||||||
public static final String NOTICE_MSG="NOTICE_MSG";//系统通知
|
|
||||||
public static final String GUARD_BUY="GUARD_BUY";//购买、续费舰长等
|
|
||||||
public static final String UNKNOWN_MESSAGE="UNKNOWN_MESSAGE";//未记录的事件
|
|
||||||
int id;
|
|
||||||
int roomId;
|
|
||||||
int uid;
|
|
||||||
String type;
|
|
||||||
String msg;
|
|
||||||
String giftName;
|
|
||||||
int giftIndex;
|
|
||||||
int giftId;
|
|
||||||
int price;
|
|
||||||
int priceOfCommission;
|
|
||||||
Date subTime;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Datas;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class LiveInfo {
|
|
||||||
int id;
|
|
||||||
int roomId;
|
|
||||||
int popular;
|
|
||||||
int userIndex;
|
|
||||||
int vipUserIndex;
|
|
||||||
Date subTime;
|
|
||||||
}
|
|
||||||
@@ -1,670 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.DanmuData;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.GiftData;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.LiveData;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
|
|
||||||
import com.yutou.bilibili.QQBot.QQBotManager;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.Tools.Log;
|
|
||||||
import com.yutou.bilibili.Tools.RedisTools;
|
|
||||||
import com.yutou.bilibili.Tools.Tools;
|
|
||||||
import com.yutou.bilibili.interfaces.DownloadInterface;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveData;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import com.yutou.bilibili.sqlite.BiliBiliLiveDatabasesManager;
|
|
||||||
import lombok.Data;
|
|
||||||
import org.java_websocket.client.WebSocketClient;
|
|
||||||
import org.java_websocket.handshake.ServerHandshake;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class Live implements ApplicationContextAware {
|
|
||||||
IBiliBiliLiveService service;
|
|
||||||
|
|
||||||
|
|
||||||
public static Map<Integer, Live> lives = new HashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
private int roomId;
|
|
||||||
private boolean isLogin;
|
|
||||||
private boolean run;
|
|
||||||
private int userId;
|
|
||||||
private WebSocketClient client;
|
|
||||||
private BilibiliLiveInfo info;
|
|
||||||
private BilibiliUpInfo upData;
|
|
||||||
private Timer heartBeattimer;
|
|
||||||
public BiliBiliLiveDatabasesManager danmuManager = null;
|
|
||||||
private LiveInfo liveInfo;
|
|
||||||
|
|
||||||
public LiveInfo getLiveInfo() {
|
|
||||||
return liveInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLiveInfo(LiveInfo liveInfo) {
|
|
||||||
this.liveInfo = liveInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Live() {
|
|
||||||
if (applicationContext != null) {
|
|
||||||
service = getBean(IBiliBiliLiveService.class);
|
|
||||||
}
|
|
||||||
info = new BilibiliLiveInfo();
|
|
||||||
info.setGiftuser(0);
|
|
||||||
info.setPopular(0);
|
|
||||||
info.setUserindex(0);
|
|
||||||
info.setVipuserindex(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构造方法
|
|
||||||
*
|
|
||||||
* @param roomId 直播间roomId,不是房间号,有可能是临时房间号,得通过 {@link com.yutou.bilibili.BiliBili.Tools.BiliTools#getBiliUpInfo(String)} 来获取roomId
|
|
||||||
* @param isLogin 是否登录用户
|
|
||||||
*/
|
|
||||||
public void add(int roomId, boolean isLogin) {
|
|
||||||
if (Live.lives.containsKey(roomId)) {
|
|
||||||
Log.i("已经在统计:" + roomId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.roomId = roomId;
|
|
||||||
this.isLogin = isLogin;
|
|
||||||
upData = new BilibiliUpInfo();
|
|
||||||
upData.setRoomid(roomId);
|
|
||||||
info.setRoomid(roomId);
|
|
||||||
info.setGiftuser(0);
|
|
||||||
info.setVipuserindex(0);
|
|
||||||
info.setUserindex(0);
|
|
||||||
Live.lives.put(roomId, this);
|
|
||||||
updateUpInfo();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("roomId = " + roomId + ", isLogin = " + isLogin);
|
|
||||||
try {
|
|
||||||
start();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateUpInfo() {
|
|
||||||
try {
|
|
||||||
upData = service.queryUp(upData);
|
|
||||||
//upData.setLive(1);
|
|
||||||
if (upData.getSavedanmu() == 1) {
|
|
||||||
danmuManager = new BiliBiliLiveDatabasesManager();
|
|
||||||
danmuManager.init("[" + AppTools.getToDayTime() + "]" + upData.getRoomid());
|
|
||||||
} else {
|
|
||||||
if (danmuManager != null) {
|
|
||||||
danmuManager.close();
|
|
||||||
danmuManager = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date startTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始监听
|
|
||||||
*
|
|
||||||
* @throws Exception 发生异常
|
|
||||||
*/
|
|
||||||
private void start() throws Exception {
|
|
||||||
run = true;
|
|
||||||
String url = LiveUtils.getLiveUrl(roomId);
|
|
||||||
if (url == null) {
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
upData.checkLiveStatus();
|
|
||||||
startTime = new Date();
|
|
||||||
HashMap<String, String> header = new HashMap<>();
|
|
||||||
header.put("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits");
|
|
||||||
header.put("Sec-WebSocket-Key", "tORCZd8AI6xIyvqvgvI1Vw==");
|
|
||||||
header.put("Sec-WebSocket-Version", "13");
|
|
||||||
header.put("Cache-Control", "no-cache");
|
|
||||||
header.put("Connection", "Upgrade");
|
|
||||||
header.put("Host", "tx-gz-live-comet-02.chat.bilibili.com");
|
|
||||||
header.put("Origin", "https://live.bilibili.com");
|
|
||||||
header.put("Pragma", "no-cache");
|
|
||||||
header.put("Upgrade", "websocket");
|
|
||||||
header.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36");
|
|
||||||
if (client != null && !client.isClosed()) {
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client = new WebSocketClient(new URI(url), header) {
|
|
||||||
private long time = 0;
|
|
||||||
private boolean init = true;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOpen(ServerHandshake serverHandshake) {
|
|
||||||
time = System.currentTimeMillis();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("ws: ok");
|
|
||||||
try {
|
|
||||||
likeLive();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(String s) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(ByteBuffer bytes) {
|
|
||||||
super.onMessage(bytes);
|
|
||||||
if (init) {
|
|
||||||
heartBeattimer = new Timer();
|
|
||||||
heartBeattimer.schedule(new sendHeartbeat(), 2000, 20000);
|
|
||||||
init = false;
|
|
||||||
}
|
|
||||||
decompress(bytes.array());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClose(int i, String s, boolean b) {
|
|
||||||
com.yutou.bilibili.Tools.Log.i("连接时间:" + (System.currentTimeMillis() - time));
|
|
||||||
if (upData.getOfflinelistening() == 1) {
|
|
||||||
Log.i(roomId + " 断开连接,重连...");
|
|
||||||
try {
|
|
||||||
init = true;
|
|
||||||
if(heartBeattimer!=null) {
|
|
||||||
heartBeattimer.cancel();
|
|
||||||
}
|
|
||||||
if(client!=null) {
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
start();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stop();
|
|
||||||
client.close();
|
|
||||||
run = false;
|
|
||||||
throw new RuntimeException("连接关闭: code = " + i + " msg = " + s + " b = " + b + " roomId=" + roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClosing(int code, String reason, boolean remote) {
|
|
||||||
super.onClosing(code, reason, remote);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("code = " + code + ", reason = " + reason + ", remote = " + remote);
|
|
||||||
run = false;
|
|
||||||
client.close();
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
run = false;
|
|
||||||
client.close();
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
client.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
run = false;
|
|
||||||
client.close();
|
|
||||||
if (danmuManager != null) {
|
|
||||||
danmuManager.close();
|
|
||||||
}
|
|
||||||
if (SaveLive.getInstance().checkLive(roomId)) {
|
|
||||||
SaveLive.getInstance().stop(roomId);
|
|
||||||
}
|
|
||||||
Live.lives.remove(roomId);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("退出" + roomId + "直播间");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 连接房间
|
|
||||||
*
|
|
||||||
* @throws Exception e
|
|
||||||
*/
|
|
||||||
private void likeLive() throws Exception {
|
|
||||||
JSONObject tmp = LiveUtils.http_get("https://api.bilibili.com/x/web-interface/nav");
|
|
||||||
if (tmp != null && tmp.getInteger("code") == -101) {
|
|
||||||
if (isLogin) {
|
|
||||||
new File("cookies.json").deleteOnExit();
|
|
||||||
upData.setLive(0);
|
|
||||||
service.updateUpInfo(upData);
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
userId = 0;
|
|
||||||
}
|
|
||||||
} else if (tmp != null && tmp.getInteger("code") == 0) {
|
|
||||||
userId = tmp.getJSONObject("data").getInteger("mid");
|
|
||||||
}
|
|
||||||
JSONObject http = LiveUtils.http_get("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=" + roomId + "&type=0");
|
|
||||||
if (http == null) {
|
|
||||||
stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("uid", userId);
|
|
||||||
json.put("roomid", roomId);
|
|
||||||
json.put("protover", 2);
|
|
||||||
json.put("platform", "web");
|
|
||||||
json.put("clientver", "2.6.36");
|
|
||||||
json.put("type", 2);
|
|
||||||
json.put("key", http.getJSONObject("data").getString("token"));
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
outputStream.write(LiveUtils.toLH(json.toJSONString().length() + 16));
|
|
||||||
outputStream.write(new byte[]{0, 16, 0, 1, 0, 0, 0, 7, 0, 0, 0, 1});
|
|
||||||
outputStream.write(json.toJSONString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
outputStream.flush();
|
|
||||||
// LiveUtils.printHex(outputStream.toByteArray());
|
|
||||||
client.send(outputStream.toByteArray());
|
|
||||||
checkLive();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解压缩
|
|
||||||
*
|
|
||||||
* @param data 待压缩的数据
|
|
||||||
*/
|
|
||||||
public void decompress(byte[] data) {
|
|
||||||
try {
|
|
||||||
byte[] bytes = new byte[data.length - 16];
|
|
||||||
System.arraycopy(data, 16, bytes, 0, data.length - 16);
|
|
||||||
|
|
||||||
if (data.length > 32) {
|
|
||||||
List<String> list = LiveUtils.getMsgList(LiveUtils.dec(bytes), new ArrayList<>(), true);
|
|
||||||
String tmp = "";
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
|
||||||
processData(list.get(i), data);
|
|
||||||
tmp += "|||" + i + "[start] " + list.get(i) + " [end]||| ";
|
|
||||||
}
|
|
||||||
// Log.i(AppTools.getToDayTimeToString(startTime), roomId, "list size = " + list.size() + " data = " + tmp);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
JSONObject json = JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8));
|
|
||||||
System.out.println("json = " + json);
|
|
||||||
com.yutou.bilibili.Tools.Log.i(json.toJSONString());
|
|
||||||
} catch (Exception e) {
|
|
||||||
int popular = LiveUtils.bytesToInt2(bytes, 0);
|
|
||||||
info.setPopular(popular);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upData.setLive(LiveUtils.getLiveState(roomId) ? 1 : 0);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("----------ERROR----------");
|
|
||||||
com.yutou.bilibili.Tools.Log.i(new String(data, StandardCharsets.UTF_8));
|
|
||||||
LiveUtils.printHex(LiveUtils.dec(data));
|
|
||||||
com.yutou.bilibili.Tools.Log.i(new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkLive() {
|
|
||||||
boolean isLive = upData.checkLiveStatus() == 1;
|
|
||||||
if (SaveLive.getInstance().checkLive(roomId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isLive && upData.getSavelive() == 1) {
|
|
||||||
SaveLive.getInstance().addLive(this);
|
|
||||||
}
|
|
||||||
if (!isLive || upData.getSavelive() == 0) {
|
|
||||||
if (SaveLive.getInstance().checkLive(roomId)) {
|
|
||||||
SaveLive.getInstance().stop(roomId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理数据
|
|
||||||
*
|
|
||||||
* @param msg 数据json
|
|
||||||
* @param bytes 原始hex数据
|
|
||||||
*/
|
|
||||||
public void processData(String msg, byte[] bytes) {
|
|
||||||
if (msg.contains("[object Object]")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
JSONObject json = JSONObject.parseObject(msg);
|
|
||||||
JSONObject data;
|
|
||||||
BilibiliLiveData liveData = new BilibiliLiveData();
|
|
||||||
String danmu;
|
|
||||||
GiftData giftData;
|
|
||||||
Log.i(AppTools.getToDayTime(), roomId, json.toJSONString());
|
|
||||||
switch (json.getString("cmd")) {
|
|
||||||
case "INTERACT_WORD"://普通用户进直播间
|
|
||||||
danmu = json.getJSONObject("data").getString("uname") + " 进入到直播间";
|
|
||||||
liveData.setUid(json.getJSONObject("data").getInteger("uid"));
|
|
||||||
liveData.setType(LiveData.INTERACT_WORD);
|
|
||||||
liveData.setMsg(danmu);
|
|
||||||
liveData.setRoomid(roomId);
|
|
||||||
liveData.setSubtime(new Date());
|
|
||||||
service.addLiveData(liveData);
|
|
||||||
break;
|
|
||||||
case "DANMU_MSG"://普通弹幕
|
|
||||||
JSONArray infoData = json.getJSONArray("info");
|
|
||||||
danmu = json.getJSONArray("info").getString(1);
|
|
||||||
DanmuData danmuData = new DanmuData();
|
|
||||||
danmuData.setModel(infoData.getJSONArray(0).getInteger(1));
|
|
||||||
danmuData.setFontSize(infoData.getJSONArray(0).getInteger(2));
|
|
||||||
danmuData.setFontColor(infoData.getJSONArray(0).getInteger(3));
|
|
||||||
danmuData.setTime(infoData.getJSONArray(0).getLong(4));
|
|
||||||
danmuData.setUCode(infoData.getJSONArray(0).getString(7));
|
|
||||||
danmuData.setDanmu(danmu);
|
|
||||||
danmuData.setUid(infoData.getJSONArray(2).getInteger(0));
|
|
||||||
danmuData.setUname(infoData.getJSONArray(2).getString(1));
|
|
||||||
|
|
||||||
if (upData != null && upData.getSavedanmu() == 1) {
|
|
||||||
if (danmuManager != null) {
|
|
||||||
danmuManager.addDanmu(danmuData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "SEND_GIFT"://送礼
|
|
||||||
data = json.getJSONObject("data");
|
|
||||||
giftData = getGiftData(data.getInteger("giftId"));
|
|
||||||
if (giftData == null) {
|
|
||||||
giftData = new GiftData();
|
|
||||||
giftData.setName(data.getString("giftName"));
|
|
||||||
giftData.setId(data.getInteger("giftId"));
|
|
||||||
giftData.setPrice(data.getInteger("price"));
|
|
||||||
giftData.setIcon("");
|
|
||||||
giftData.setDesc("这是阿B没有收录的礼物,金额可能不准(无法判别为免费礼物)");
|
|
||||||
giftData.setRights("?");
|
|
||||||
}
|
|
||||||
danmu = data.getString("uname") + " " + data.getString("action") + " " + giftData.getName();
|
|
||||||
liveData.setType(LiveData.SEND_GIFT);
|
|
||||||
liveData.setUid(data.getInteger("uid"));
|
|
||||||
liveData.setGiftid(giftData.getId());
|
|
||||||
liveData.setGiftindex(data.getInteger("num"));
|
|
||||||
liveData.setGiftname(giftData.getName());
|
|
||||||
liveData.setMsg(danmu);
|
|
||||||
liveData.setPrice(giftData.getPrice());
|
|
||||||
liveData.setPriceofcommission(giftData.getPrice() == 0 ? 0 : giftData.getPrice() / 2);
|
|
||||||
liveData.setSubtime(new Date());
|
|
||||||
liveData.setRoomid(roomId);
|
|
||||||
info.setGiftuser(info.getGiftuser() + 1);
|
|
||||||
service.addLiveData(liveData);
|
|
||||||
break;
|
|
||||||
case "COMBO_SEND"://礼物连击
|
|
||||||
data = json.getJSONObject("data");
|
|
||||||
String gift = data.getString("giftName");
|
|
||||||
if (gift == null || "null".equals(gift)) {
|
|
||||||
gift = data.getString("gift_name");
|
|
||||||
}
|
|
||||||
danmu = data.getString("uname") + " " + data.getString("action") + " " + gift + "x" + data.getInteger("batch_combo_num");
|
|
||||||
giftData = getGiftData(data.getInteger("gift_id"));
|
|
||||||
if (giftData == null) {
|
|
||||||
giftData = new GiftData();
|
|
||||||
giftData.setName(data.getString("giftName"));
|
|
||||||
giftData.setId(data.getInteger("giftId"));
|
|
||||||
giftData.setPrice(data.getInteger("price"));
|
|
||||||
giftData.setIcon("");
|
|
||||||
giftData.setDesc("这是阿B没有收录的礼物,金额可能不准(无法判别为免费礼物)");
|
|
||||||
giftData.setRights("?");
|
|
||||||
}
|
|
||||||
liveData.setType(LiveData.COMBO_SEND);
|
|
||||||
liveData.setUid(data.getInteger("uid"));
|
|
||||||
liveData.setGiftid(giftData.getId());
|
|
||||||
liveData.setGiftindex(data.getInteger("batch_combo_num"));
|
|
||||||
liveData.setGiftname(giftData.getName());
|
|
||||||
liveData.setMsg(danmu);
|
|
||||||
liveData.setPrice(giftData.getPrice() * liveData.getGiftindex());
|
|
||||||
liveData.setPriceofcommission(giftData.getPrice() == 0 ? 0 : giftData.getPrice() / 2);
|
|
||||||
liveData.setSubtime(new Date());
|
|
||||||
liveData.setRoomid(roomId);
|
|
||||||
info.setGiftuser(info.getGiftuser() + 1);
|
|
||||||
service.addLiveData(liveData);
|
|
||||||
break;
|
|
||||||
case "ENTRY_EFFECT"://舰长进直播间
|
|
||||||
info.setVipuserindex(info.getVipuserindex() + 1);
|
|
||||||
danmu = "[舰长]" + json.getJSONObject("data").getString("uid") + " 进入到直播间";
|
|
||||||
liveData.setUid(json.getJSONObject("data").getInteger("uid"));
|
|
||||||
liveData.setType(LiveData.ENTRY_EFFECT);
|
|
||||||
liveData.setMsg(danmu);
|
|
||||||
liveData.setRoomid(roomId);
|
|
||||||
liveData.setSubtime(new Date());
|
|
||||||
service.addLiveData(liveData);
|
|
||||||
break;
|
|
||||||
case "LIVE_INTERACTIVE_GAME"://彩色弹幕?通过游戏弹幕
|
|
||||||
break;
|
|
||||||
case "SUPER_CHAT_MESSAGE"://SC
|
|
||||||
data = json.getJSONObject("data");
|
|
||||||
danmu = data.getJSONObject("user_info").getString("uname") + " "
|
|
||||||
+ data.getJSONObject("gift").getString("gift_name") + " " + data.getInteger("price") + "元: " + data.getString("message");
|
|
||||||
liveData.setType(LiveData.SUPER_CHAT_MESSAGE);
|
|
||||||
liveData.setUid(data.getInteger("uid"));
|
|
||||||
liveData.setMsg(danmu);
|
|
||||||
liveData.setGiftid(0);
|
|
||||||
liveData.setRoomid(roomId);
|
|
||||||
liveData.setGiftname(data.getJSONObject("gift").getString("gift_name"));
|
|
||||||
liveData.setGiftindex(1);
|
|
||||||
liveData.setPrice(data.getInteger("price") * 1000);
|
|
||||||
liveData.setPriceofcommission(liveData.getPrice() == 0 ? 0 : liveData.getPrice() / 2);
|
|
||||||
liveData.setSubtime(new Date());
|
|
||||||
info.setGiftuser(info.getGiftuser() + 1);
|
|
||||||
service.addLiveData(liveData);
|
|
||||||
break;
|
|
||||||
case "USER_TOAST_MSG":
|
|
||||||
break;
|
|
||||||
case "GUARD_BUY"://开通/续费 牛逼的东西
|
|
||||||
data = json.getJSONObject("data");
|
|
||||||
liveData.setType(LiveData.GUARD_BUY);
|
|
||||||
liveData.setUid(data.getInteger("uid"));
|
|
||||||
liveData.setMsg(data.getString("gift_name"));
|
|
||||||
liveData.setGiftid(-data.getInteger("guard_level"));
|
|
||||||
liveData.setGiftindex(data.getInteger("num"));
|
|
||||||
liveData.setGiftname(data.getString("gift_name"));
|
|
||||||
liveData.setPrice(data.getInteger("price"));
|
|
||||||
liveData.setPriceofcommission(liveData.getPrice() == 0 ? 0 : liveData.getPrice() / 2);
|
|
||||||
liveData.setSubtime(new Date());
|
|
||||||
liveData.setRoomid(roomId);
|
|
||||||
info.setGiftuser(info.getGiftuser() + 1);
|
|
||||||
service.addLiveData(liveData);
|
|
||||||
break;
|
|
||||||
case "LIVE"://开始直播,不过有在心跳包上做检测了,所以也无所谓?
|
|
||||||
|
|
||||||
JSONObject liveInfo = LiveUtils.getLiveInfo(upData);
|
|
||||||
if (liveInfo == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
upData.setLive(liveInfo.getInteger("live_status"));
|
|
||||||
LiveInfo info = new LiveInfo();
|
|
||||||
info.setTitle(liveInfo.getString("title"));
|
|
||||||
info.setKeyframe(liveInfo.getString("keyframe"));
|
|
||||||
info.setRoomId(liveInfo.getInteger("room_id"));
|
|
||||||
info.setShortId(liveInfo.getInteger("short_id"));
|
|
||||||
info.setInfo(liveInfo);
|
|
||||||
setLiveInfo(info);
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append(upData.getName()).append("开播了!").append("\n");
|
|
||||||
builder.append(info.getTitle());
|
|
||||||
Tools.download(info.getKeyframe(), new DownloadInterface() {
|
|
||||||
@Override
|
|
||||||
public void onDownload(File file) {
|
|
||||||
super.onDownload(file);
|
|
||||||
QQBotManager.getInstance().sendMessage(file, builder.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "PREPARING"://直播结束
|
|
||||||
upData.setLive(0);
|
|
||||||
break;
|
|
||||||
case "WATCHED_CHANGE"://人气值
|
|
||||||
try {
|
|
||||||
Live.this.info.setPopular(Integer.getInteger(json.getJSONObject("data").getString("text_small")));
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "SUPER_CHAT_MESSAGE_JPN":
|
|
||||||
case "NOTICE_MSG":
|
|
||||||
case "HOT_RANK_CHANGED"://榜单更新等无用信息
|
|
||||||
case "ONLINE_RANK_COUNT":
|
|
||||||
case "ONLINE_RANK_V2":
|
|
||||||
case "ONLINE_RANK_TOP3":
|
|
||||||
case "ROOM_REAL_TIME_MESSAGE_UPDATE":
|
|
||||||
case "WIDGET_BANNER"://鬼知道是啥
|
|
||||||
case "HOT_RANK_SETTLEMENT":
|
|
||||||
case "PK_BATTLE_SETTLE_V2":
|
|
||||||
case "PK_BATTLE_END":
|
|
||||||
case "PK_BATTLE_SETTLE":
|
|
||||||
case "PK_BATTLE_PRE_NEW":
|
|
||||||
case "PK_BATTLE_PRE":
|
|
||||||
case "STOP_LIVE_ROOM_LIST"://不知道是啥,停止直播?
|
|
||||||
|
|
||||||
|
|
||||||
//com.yutou.bilibili.Tools.Log.i(msg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
com.yutou.bilibili.Tools.Log.i("[" + roomId + "]" + msg);
|
|
||||||
liveData = new BilibiliLiveData();
|
|
||||||
liveData.setType(LiveData.UNKNOWN_MESSAGE);
|
|
||||||
liveData.setUid(-1);
|
|
||||||
liveData.setMsg(msg);
|
|
||||||
liveData.setRoomid(roomId);
|
|
||||||
liveData.setSubtime(new Date());
|
|
||||||
service.addLiveData(liveData);
|
|
||||||
}
|
|
||||||
checkLive();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
Log.i("msg = " + msg);
|
|
||||||
// Log.i(AppTools.getToDayTimeToString(startTime), roomId, e.getLocalizedMessage());
|
|
||||||
/*try {
|
|
||||||
JSONObject.parseObject(new String(bytes, StandardCharsets.UTF_8));
|
|
||||||
processData(new String(bytes, StandardCharsets.UTF_8), null);
|
|
||||||
} catch (Exception e2) {
|
|
||||||
try {
|
|
||||||
JSONObject.parseObject(msg);
|
|
||||||
processData(msg, bytes);
|
|
||||||
} catch (Exception e3) {
|
|
||||||
Log.e(e2);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("---------ERROR !! start-----");
|
|
||||||
com.yutou.bilibili.Tools.Log.i(msg);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("---------ERROR !! end-----");
|
|
||||||
// LiveUtils.printHex(bytes);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearInfo() {
|
|
||||||
info = new BilibiliLiveInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BilibiliLiveInfo getInfo() {
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSaveDanmo(boolean saveDanmu) {
|
|
||||||
upData.setSavedanmu(saveDanmu ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ApplicationContext applicationContext = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
|
|
||||||
if (Live.applicationContext == null) {
|
|
||||||
Live.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getBean(Class<T> clazz) {
|
|
||||||
return applicationContext.getBean(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BilibiliUpInfo geData() {
|
|
||||||
return upData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送心跳包
|
|
||||||
*/
|
|
||||||
public class sendHeartbeat extends TimerTask {
|
|
||||||
|
|
||||||
public sendHeartbeat() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (!run) {
|
|
||||||
cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateUpInfo();
|
|
||||||
if (upData.getOfflinelistening() != 1) {
|
|
||||||
if (upData.getLive() == 0) {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// com.yutou.bilibili.Tools.Log.i("-------发送心跳--------");
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
outputStream.write(LiveUtils.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();
|
|
||||||
client.send(outputStream.toByteArray());
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(e);
|
|
||||||
com.yutou.bilibili.Tools.Log.i(client.isClosed());
|
|
||||||
com.yutou.bilibili.Tools.Log.i(client.isOpen());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GiftData getGiftData(int id) {
|
|
||||||
JSONObject item = JSONObject.parseObject(RedisTools.get("bili_gift_" + id, 2));
|
|
||||||
GiftData data = new GiftData();
|
|
||||||
data.setPrice(item.getInteger("price"));
|
|
||||||
data.setName(item.getString("name"));
|
|
||||||
data.setId(item.getInteger("id"));
|
|
||||||
data.setRights(item.getString("rights"));
|
|
||||||
data.setIcon(item.getString("img_basic"));
|
|
||||||
data.setDesc(item.getString("desc"));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class LiveInfo {
|
|
||||||
private String title;
|
|
||||||
private String keyframe;
|
|
||||||
private int roomId;
|
|
||||||
private int shortId;
|
|
||||||
private JSONObject info;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Timer;
|
|
||||||
|
|
||||||
public class LiveController {
|
|
||||||
private static LiveController controller;
|
|
||||||
private Timer timer;
|
|
||||||
|
|
||||||
public static LiveController getInstance() {
|
|
||||||
if (controller == null) {
|
|
||||||
controller = new LiveController();
|
|
||||||
}
|
|
||||||
return controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LiveController() {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateUpInfo(BilibiliUpInfo data) {
|
|
||||||
Live live = LiveUtils.liveContains(data);
|
|
||||||
if (live != null) {
|
|
||||||
live.setSaveDanmo(data.getSavedanmu() == 1);
|
|
||||||
boolean saveLive=SaveLive.getInstance().checkLive(data.getRoomid());
|
|
||||||
if(data.getSavelive()==1){
|
|
||||||
if(!saveLive){
|
|
||||||
SaveLive.getInstance().addLive(live);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if(saveLive){
|
|
||||||
SaveLive.getInstance().stop(data.getRoomid());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.getEnable()==1||data.getOfflinelistening()==1) {
|
|
||||||
if (live == null) {
|
|
||||||
live=new Live();
|
|
||||||
live.add(data.getRoomid(), !StringUtils.isEmpty(AppTools.readFile(new File("cookies.json"))));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (live != null) {
|
|
||||||
live.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,450 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.BiliBiliUpData;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.GiftData;
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.Tools.HttpTools;
|
|
||||||
import com.yutou.bilibili.Tools.Log;
|
|
||||||
import com.yutou.bilibili.Tools.RedisTools;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.zip.Inflater;
|
|
||||||
|
|
||||||
public class LiveUtils {
|
|
||||||
private static String cookie = null;
|
|
||||||
private static Map<Integer, Boolean> liveStateMap = new HashMap<>();
|
|
||||||
|
|
||||||
public LiveUtils() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static String getLiveUrl(int roomId) {
|
|
||||||
JSONObject json = http_get("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=" + roomId + "&type=0");
|
|
||||||
if (json != null) {
|
|
||||||
return "wss://" + json.getJSONObject("data").getJSONArray("host_list").getJSONObject(0).getString("host") + "/sub";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void printHex(byte[] bytes) {
|
|
||||||
String str = DatatypeConverter.printHexBinary(bytes);
|
|
||||||
for (int i = 0; i < str.length(); i = i + 4) {
|
|
||||||
if (i % 32 == 0 && i != 0) {
|
|
||||||
com.yutou.bilibili.Tools.Log.i("\n");
|
|
||||||
}
|
|
||||||
if (str.length() - i > 4) {
|
|
||||||
com.yutou.bilibili.Tools.Log.i(str.substring(i, i + 4));
|
|
||||||
} else {
|
|
||||||
com.yutou.bilibili.Tools.Log.i(str.substring(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getHex(byte[] bytes) {
|
|
||||||
return DatatypeConverter.printHexBinary(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] dec(byte[] data) {
|
|
||||||
byte[] output = new byte[0];
|
|
||||||
|
|
||||||
Inflater decompresser = new Inflater();
|
|
||||||
decompresser.reset();
|
|
||||||
decompresser.setInput(data);
|
|
||||||
|
|
||||||
ByteArrayOutputStream o = new ByteArrayOutputStream(data.length);
|
|
||||||
try {
|
|
||||||
byte[] buf = new byte[1024];
|
|
||||||
while (!decompresser.finished()) {
|
|
||||||
int i = decompresser.inflate(buf);
|
|
||||||
o.write(buf, 0, i);
|
|
||||||
}
|
|
||||||
output = o.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
try {
|
|
||||||
JSONObject json = JSONObject.parseObject(new String(data, StandardCharsets.UTF_8));
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
// outputStream.write(toLH(json.toJSONString().length() + 16));
|
|
||||||
//outputStream.write(new byte[]{0, 16, 0, 1, 0, 0, 0, 5, 0, 0, 0, 1});
|
|
||||||
outputStream.write(json.toJSONString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
output = outputStream.toByteArray();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
output = data;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
o.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decompresser.end();
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> getMsgList(byte[] bytes, List<String> list, boolean isOne) {
|
|
||||||
int len = 16;
|
|
||||||
ByteBuffer datas = ByteBuffer.allocate(bytes.length - len);
|
|
||||||
byte[] heads = new byte[4];
|
|
||||||
//获取到头信息
|
|
||||||
System.arraycopy(bytes, 0, heads, 0, 4);
|
|
||||||
int size = bytesToInt2(heads, 0) - 16;
|
|
||||||
|
|
||||||
//datas=MainApp.dec(datas);
|
|
||||||
if (size == datas.array().length) {
|
|
||||||
System.arraycopy(bytes, len, datas.array(), 0, bytes.length - len);
|
|
||||||
list.add(new String(datas.array(), StandardCharsets.UTF_8));
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
// com.yutou.bilibili.Tools.Log.i("datas size = " + size);
|
|
||||||
if (size > 1000000000) {
|
|
||||||
try {
|
|
||||||
JSONObject.parseObject(new String(bytes));
|
|
||||||
list.add(new String(bytes, StandardCharsets.UTF_8));
|
|
||||||
return list;
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
datas.clear();
|
|
||||||
datas = ByteBuffer.allocate(size);
|
|
||||||
System.arraycopy(bytes, len, datas.array(), 0, size);
|
|
||||||
list.add(new String(datas.array(), StandardCharsets.UTF_8));
|
|
||||||
byte[] tmps = new byte[bytes.length - size - 16];
|
|
||||||
int length = bytes.length - (size + len);
|
|
||||||
System.arraycopy(bytes, size + (len), tmps, 0, length);
|
|
||||||
|
|
||||||
getMsgList(tmps, list, false);
|
|
||||||
} catch (Exception e) {
|
|
||||||
list.add(new String(bytes, StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 String getCookie() {
|
|
||||||
if (StringUtils.isEmpty(getFile("cookies.json"))) {
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
JSONObject json = JSONObject.parseObject(getFile("cookies.json"));
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
for (String s : json.keySet()) {
|
|
||||||
builder.append(s).append("=").append(json.getString(s)).append(";");
|
|
||||||
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public static String createCookie(){
|
|
||||||
String bid="AUTO"+AppTools.randomString(16,new String[]{AppTools.numbers});
|
|
||||||
bid="AUTO6616152607312876";
|
|
||||||
return String.format("LIVE_BUVID=%s; _uuid=%sinfoc; buvid3=%sinfoc; sid=%s; fingerprint=%s; buvid_fp=%sinfoc; buvid_fp_plain=%sinfoc; PVID=%d;"
|
|
||||||
,bid
|
|
||||||
,UUID.randomUUID().toString()
|
|
||||||
,UUID.randomUUID().toString()
|
|
||||||
,"bm3byv4p"
|
|
||||||
,"074eae35a01a56c40558a54ab33179e5"
|
|
||||||
,UUID.randomUUID().toString()
|
|
||||||
,UUID.randomUUID().toString()
|
|
||||||
,AppTools.randomCommon(0,9,1)[0]);
|
|
||||||
}*/
|
|
||||||
private static long oldBiliBiliHttpTime = 0;
|
|
||||||
|
|
||||||
public synchronized static JSONObject http_get(String url) {
|
|
||||||
try {
|
|
||||||
// Log.i("调用url = "+url);
|
|
||||||
HttpURLConnection connection = getBiliHttpGet(url, getCookie());
|
|
||||||
BufferedInputStream stream = new BufferedInputStream(connection.getInputStream());
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int len = 0, size;
|
|
||||||
while ((len = stream.read(bytes)) != -1) {
|
|
||||||
outputStream.write(bytes, 0, len);
|
|
||||||
outputStream.flush();
|
|
||||||
}
|
|
||||||
String str = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
|
|
||||||
outputStream.close();
|
|
||||||
try {
|
|
||||||
JSONObject json = JSON.parseObject(str);
|
|
||||||
return json;
|
|
||||||
} catch (Exception e) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("html", str);
|
|
||||||
return json;
|
|
||||||
} finally {
|
|
||||||
|
|
||||||
stream.close();
|
|
||||||
connection.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
//com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
Log.e(e);
|
|
||||||
Log.i("412 in " + url);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONObject http_post(String url, String body) {
|
|
||||||
try {
|
|
||||||
if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(500);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
oldBiliBiliHttpTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
HttpURLConnection connection = getBiliHttpPost(url, getCookie());
|
|
||||||
OutputStream connectionOutputStream = null;
|
|
||||||
if (!StringUtils.isEmpty(body)) {
|
|
||||||
connectionOutputStream = connection.getOutputStream();
|
|
||||||
connectionOutputStream.write(body.getBytes(StandardCharsets.UTF_8));
|
|
||||||
connectionOutputStream.flush();
|
|
||||||
}
|
|
||||||
BufferedInputStream stream = new BufferedInputStream(connection.getInputStream());
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int len = 0, size;
|
|
||||||
while ((len = stream.read(bytes)) != -1) {
|
|
||||||
outputStream.write(bytes, 0, len);
|
|
||||||
outputStream.flush();
|
|
||||||
}
|
|
||||||
String str = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
|
|
||||||
outputStream.close();
|
|
||||||
try {
|
|
||||||
JSONObject json = JSON.parseObject(str);
|
|
||||||
json.put("cookie", connection.getHeaderField("Set-Cookie"));
|
|
||||||
return json;
|
|
||||||
} catch (Exception e) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("html", str);
|
|
||||||
json.put("cookie", connection.getHeaderField("Set-Cookie"));
|
|
||||||
return json;
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
if (connectionOutputStream != null) {
|
|
||||||
connectionOutputStream.close();
|
|
||||||
}
|
|
||||||
connection.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
return new JSONObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpURLConnection getBiliHttpPost(String url, String cookie) throws Exception {
|
|
||||||
if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(500);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
oldBiliBiliHttpTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
connection.setDoInput(true);
|
|
||||||
connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
|
|
||||||
connection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
|
|
||||||
connection.setRequestProperty("Cache-Control", "max-age=0");
|
|
||||||
connection.setRequestProperty("Referer", "https://live.bilibili.com");
|
|
||||||
connection.setRequestProperty("Connection", "keep-alive");
|
|
||||||
connection.setRequestProperty("Upgrade-Insecure-Requests", "1");
|
|
||||||
connection.setRequestProperty("Cookie", cookie);
|
|
||||||
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36");
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpURLConnection getBiliHttpGet(String url, String cookie) throws IOException {
|
|
||||||
if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(500);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
oldBiliBiliHttpTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
|
||||||
connection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
|
|
||||||
connection.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
|
|
||||||
connection.setRequestProperty("Cache-Control", "max-age=0");
|
|
||||||
connection.setRequestProperty("Referer", "https://live.bilibili.com");
|
|
||||||
connection.setRequestProperty("Connection", "keep-alive");
|
|
||||||
connection.setRequestProperty("Upgrade-Insecure-Requests", "1");
|
|
||||||
connection.setRequestProperty("Cookie", cookie);
|
|
||||||
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36");
|
|
||||||
connection.setReadTimeout(5000);
|
|
||||||
connection.setConnectTimeout(5000);
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static String getFile(String filePath) {
|
|
||||||
File file = new File(filePath);
|
|
||||||
try {
|
|
||||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
|
||||||
String str = "", tmp;
|
|
||||||
while ((tmp = reader.readLine()) != null) {
|
|
||||||
str += tmp;
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
return str;
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static JSONObject getUserLoginInfo() {
|
|
||||||
return LiveUtils.http_get("https://api.bilibili.com/x/web-interface/nav");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Live liveContains(BilibiliUpInfo data) {
|
|
||||||
for (Live live : Live.lives.values()) {
|
|
||||||
if (live.getInfo().getRoomid().equals(data.getRoomid())) {
|
|
||||||
return live;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long getMid(int roomId) {
|
|
||||||
JSONObject http_get = http_get("https://api.live.bilibili.com/room/v1/Room/room_init?id=" + roomId);
|
|
||||||
if (http_get == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (http_get.getInteger("code") == 0) {
|
|
||||||
return http_get.getJSONObject("data").getLong("uid");
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONObject getLiveInfo(BilibiliUpInfo info) {
|
|
||||||
List<BilibiliUpInfo> list = new ArrayList<>();
|
|
||||||
list.add(info);
|
|
||||||
JSONObject infoByUid = getStatusInfoByUid(list);
|
|
||||||
return infoByUid.getJSONObject("data").getJSONObject(info.getMid() + "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONObject getLiveRoomInfo(int roomId) {
|
|
||||||
String url = "https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id=" + roomId + "&protocol=0,1&format=0,1,2&codec=0,1&qn=10000&platform=web&ptype=8";
|
|
||||||
return http_get(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean getLiveState(int roomId) {
|
|
||||||
return liveStateMap.getOrDefault(roomId, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JSONObject getStatusInfoByUid(List<BilibiliUpInfo> list) {
|
|
||||||
JSONArray userId = new JSONArray();
|
|
||||||
for (BilibiliUpInfo info : list) {
|
|
||||||
userId.add(info.getMid());
|
|
||||||
}
|
|
||||||
JSONObject json=new JSONObject();
|
|
||||||
json.put("uids",userId);
|
|
||||||
return JSONObject.parseObject(HttpTools.post("https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids", json.toJSONString().getBytes(StandardCharsets.UTF_8)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void reloadLiveState(List<BilibiliUpInfo> list) {
|
|
||||||
JSONObject json = getStatusInfoByUid(list);
|
|
||||||
try {
|
|
||||||
if (json.getInteger("code") == 0) {
|
|
||||||
JSONObject data = json.getJSONObject("data");
|
|
||||||
for (BilibiliUpInfo info : list) {
|
|
||||||
if (data.containsKey(info.getMid() + "")) {
|
|
||||||
liveStateMap.put(info.getRoomid(), data.getJSONObject(info.getMid()+"").getInteger("live_status") == 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.i("live state = " + json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static boolean isLivePlayer(int roomId) {
|
|
||||||
return getLiveState(roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static class LiveGiftConfig {
|
|
||||||
@Resource
|
|
||||||
IBiliBiliLiveService service;
|
|
||||||
private static LiveGiftConfig config;
|
|
||||||
|
|
||||||
public static LiveGiftConfig getInstance() {
|
|
||||||
if (config == null) {
|
|
||||||
config = new LiveGiftConfig();
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LiveGiftConfig() {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init() {
|
|
||||||
JSONObject json = http_get("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/giftConfig?platform=pc");
|
|
||||||
if (json == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JSONArray list = json.getJSONObject("data").getJSONArray("list");
|
|
||||||
for (Object o : list) {
|
|
||||||
JSONObject item = (JSONObject) o;
|
|
||||||
RedisTools.set(2, "bili_gift_" + item.getInteger("id"), item.toJSONString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
List<BilibiliUpInfo> list=new ArrayList<>();
|
|
||||||
BilibiliUpInfo info=new BilibiliUpInfo();
|
|
||||||
info.setMid(402417817L);
|
|
||||||
list.add(info);
|
|
||||||
JSONObject infoByUid = getStatusInfoByUid(list);
|
|
||||||
System.out.println(infoByUid);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Services;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveData;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface IBiliBiliLiveService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有up信息
|
|
||||||
* @return up列表
|
|
||||||
*/
|
|
||||||
List<BilibiliUpInfo> getUpInfo();
|
|
||||||
List<BilibiliUpInfo> getUpInfo(int uid,String power);
|
|
||||||
/**
|
|
||||||
* 根据RoomId查询UP信息
|
|
||||||
* @param data roomId
|
|
||||||
* @return UP信息
|
|
||||||
*/
|
|
||||||
BilibiliUpInfo queryUp(BilibiliUpInfo data);
|
|
||||||
BilibiliUpInfo queryUpToUrl(String url);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据RoomId查询UP信息
|
|
||||||
* @param roomId roomId
|
|
||||||
* @return UP信息
|
|
||||||
*/
|
|
||||||
BilibiliUpInfo queryUpToRoomId(int roomId);
|
|
||||||
/**
|
|
||||||
* 获取所有直播数据
|
|
||||||
* @return 直播数据列表
|
|
||||||
*/
|
|
||||||
List<BilibiliLiveData> getLiveData();
|
|
||||||
/**
|
|
||||||
* 获取所有直播统计
|
|
||||||
* @return 直播统计列表
|
|
||||||
*/
|
|
||||||
List<BilibiliLiveInfo> getLiveInfo();
|
|
||||||
/**
|
|
||||||
* 添加up信息
|
|
||||||
* @param upData up信息
|
|
||||||
* @return 是否成功
|
|
||||||
*/
|
|
||||||
boolean addUpInfo(BilibiliUpInfo upData);
|
|
||||||
/**
|
|
||||||
* 更新UP信息
|
|
||||||
* @param upData up信息
|
|
||||||
* @return 是否成功
|
|
||||||
*/
|
|
||||||
boolean updateUpInfo(BilibiliUpInfo upData);
|
|
||||||
/**
|
|
||||||
* 删除指定up信息
|
|
||||||
* @param upData roomId
|
|
||||||
* @return 是否成功
|
|
||||||
*/
|
|
||||||
boolean deleteUp(BilibiliUpInfo upData);
|
|
||||||
/**
|
|
||||||
* 新增直播数据
|
|
||||||
* @param data 直播数据
|
|
||||||
* @return 是否成功
|
|
||||||
*/
|
|
||||||
boolean addLiveData(BilibiliLiveData data);
|
|
||||||
/**
|
|
||||||
* 添加直播统计
|
|
||||||
* @param data 直播统计
|
|
||||||
* @return 是否成功
|
|
||||||
*/
|
|
||||||
boolean addLiveInfo(BilibiliLiveInfo data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询指定时段直播数据
|
|
||||||
* @param roomId roomId
|
|
||||||
* @param startTime 开始时间,为空表示为当天00:00:00
|
|
||||||
* @param endTime 结束时间,为空表示为当时
|
|
||||||
* @param type 类型
|
|
||||||
* @return 列表
|
|
||||||
*/
|
|
||||||
List<BilibiliLiveData> queryLiveData(int roomId, Date startTime, Date endTime, String[] type);
|
|
||||||
/**
|
|
||||||
* 查询指定时段直播某个礼物总数
|
|
||||||
* @param roomId roomId
|
|
||||||
* @param giftId 礼物id,-1则为全部
|
|
||||||
* @param startTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @return 数量
|
|
||||||
*/
|
|
||||||
int queryGiftSize(int roomId, int giftId, Date startTime, Date endTime);
|
|
||||||
/**
|
|
||||||
* 返回指定时段各个礼物总数
|
|
||||||
* @param roomId roomId
|
|
||||||
* @param startTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @return {giftName:size}
|
|
||||||
*/
|
|
||||||
Map<String, Integer> queryGiftSize(int roomId, Date startTime, Date endTime);
|
|
||||||
/**
|
|
||||||
* 查询指定时段收益情况
|
|
||||||
* @param roomId roomId
|
|
||||||
* @param startTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @return 未扣除收成比例的金瓜子数量
|
|
||||||
*/
|
|
||||||
int queryPriceSize(int roomId, Date startTime, Date endTime);
|
|
||||||
/**
|
|
||||||
* 根据礼物id查询礼物信息,该方法主要用于阿B接口未收录的礼物信息
|
|
||||||
* @param giftId 礼物id
|
|
||||||
* @return 直播信息
|
|
||||||
*/
|
|
||||||
BilibiliLiveData queryGiftOfId(int giftId);
|
|
||||||
/**
|
|
||||||
* 查询指定时段去重送礼人数
|
|
||||||
*
|
|
||||||
* @param upData up信息
|
|
||||||
* @param startTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @param type 礼物类型
|
|
||||||
* @return 人数
|
|
||||||
*/
|
|
||||||
int queryGiftUserToDistinct(BilibiliUpInfo upData, Date startTime, Date endTime, String[] type);
|
|
||||||
/**
|
|
||||||
* 查询时段内人气数量
|
|
||||||
* @param upData up信息
|
|
||||||
* @param startTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @return 人气
|
|
||||||
*/
|
|
||||||
int queryPopularCount(BilibiliUpInfo upData,Date startTime, Date endTime);
|
|
||||||
/**
|
|
||||||
* 查询时段内进场人数
|
|
||||||
* @param upData up信息
|
|
||||||
* @param startTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @return 人数
|
|
||||||
*/
|
|
||||||
int queryUserCount(BilibiliUpInfo upData,Date startTime, Date endTime);
|
|
||||||
/**
|
|
||||||
* 查询时段内礼物详情
|
|
||||||
* @param upData up信息
|
|
||||||
* @param startTime 开始时间
|
|
||||||
* @param endTime 结束时间
|
|
||||||
* @return 人数
|
|
||||||
*/
|
|
||||||
Map<String, Integer> queryUserGiftCount(BilibiliUpInfo upData,Date startTime,Date endTime);
|
|
||||||
|
|
||||||
List<BilibiliLiveInfo> queryLiveInfo(BilibiliUpInfo upInfo,Date startTime,Date endTime);
|
|
||||||
|
|
||||||
List<Map<String, BigDecimal>>queryTimeGroup(int roomId, Date startTime, Date endTime);
|
|
||||||
|
|
||||||
List<Map<String, BigDecimal>>queryGiftTimeGroup(int roomId, Date startTime, Date endTime);
|
|
||||||
}
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Services.impl;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
|
||||||
import com.yutou.bilibili.Tools.Config;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliLiveDataDao;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliLiveInfoDao;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliUpInfoDao;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.*;
|
|
||||||
import com.yutou.bilibili.mybatis.dao.UBiliUpDao;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UBiliUp;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UBiliUpExample;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Service("BiliBiliLiveService")
|
|
||||||
public class BiliBiliLiveServiceImpl implements IBiliBiliLiveService {
|
|
||||||
@Resource
|
|
||||||
BilibiliUpInfoDao upInfoDao;
|
|
||||||
@Resource
|
|
||||||
BilibiliLiveDataDao liveDataDao;
|
|
||||||
@Resource
|
|
||||||
BilibiliLiveInfoDao liveInfoDao;
|
|
||||||
@Resource
|
|
||||||
UBiliUpDao biliUpDao;
|
|
||||||
@Resource
|
|
||||||
ISystemConfigService configService;
|
|
||||||
|
|
||||||
private <T> T getData(List<T> list) {
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return list.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<BilibiliUpInfo> getUpInfo() {
|
|
||||||
return upInfoDao.selectByExample(new BilibiliUpInfoExample());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<BilibiliUpInfo> getUpInfo(int uid, String power) {
|
|
||||||
UBiliUpExample example = new UBiliUpExample();
|
|
||||||
List<BilibiliUpInfo> upInfos = new ArrayList<>();
|
|
||||||
if (power.equals("[-1]")) {
|
|
||||||
upInfos = upInfoDao.selectByExample(new BilibiliUpInfoExample());
|
|
||||||
return upInfos;
|
|
||||||
}
|
|
||||||
example.createCriteria().andUidEqualTo(uid);
|
|
||||||
List<UBiliUp> list = biliUpDao.selectByExample(example);
|
|
||||||
int[] ids = new int[list.size()];
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
|
||||||
ids[i] = list.get(i).getRoomid();
|
|
||||||
}
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
return upInfos;
|
|
||||||
}
|
|
||||||
upInfos = upInfoDao.queryToRoomIds(ids);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("list = " + upInfos.size());
|
|
||||||
return upInfos;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BilibiliUpInfo queryUp(BilibiliUpInfo data) {
|
|
||||||
if (data.getRoomid() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return queryUpToRoomId(data.getRoomid());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BilibiliUpInfo queryUpToUrl(String url) {
|
|
||||||
BilibiliUpInfoExample example = new BilibiliUpInfoExample();
|
|
||||||
example.createCriteria().andUrlEqualTo(url);
|
|
||||||
return getData(upInfoDao.selectByExample(example));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BilibiliUpInfo queryUpToRoomId(int roomId) {
|
|
||||||
BilibiliUpInfoExample example = new BilibiliUpInfoExample();
|
|
||||||
example.createCriteria().andRoomidEqualTo(roomId);
|
|
||||||
return getData(upInfoDao.selectByExample(example));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<BilibiliLiveData> getLiveData() {
|
|
||||||
return liveDataDao.selectByExample(new BilibiliLiveDataExample());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<BilibiliLiveInfo> getLiveInfo() {
|
|
||||||
return liveInfoDao.selectByExample(new BilibiliLiveInfoExample());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addUpInfo(BilibiliUpInfo upData) {
|
|
||||||
BilibiliUpInfoExample example = new BilibiliUpInfoExample();
|
|
||||||
example.createCriteria().andRoomidEqualTo(upData.getRoomid());
|
|
||||||
if (upInfoDao.selectByExample(example).isEmpty()) {
|
|
||||||
return upInfoDao.insert(upData) > 0;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateUpInfo(BilibiliUpInfo upData) {
|
|
||||||
return upInfoDao.updateByPrimaryKey(upData) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteUp(BilibiliUpInfo upData) {
|
|
||||||
BilibiliUpInfoExample example = new BilibiliUpInfoExample();
|
|
||||||
example.createCriteria().andRoomidEqualTo(upData.getRoomid());
|
|
||||||
return upInfoDao.deleteByExample(example) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addLiveData(BilibiliLiveData data) {
|
|
||||||
if (!isLive()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return liveDataDao.insert(data) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addLiveInfo(BilibiliLiveInfo data) {
|
|
||||||
if (!isLive()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return liveInfoDao.insert(data) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<BilibiliLiveData> queryLiveData(int roomId, Date startTime, Date endTime, String[] type) {
|
|
||||||
return liveDataDao.queryLiveData(roomId, startTime, endTime, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int queryGiftSize(int roomId, int giftId, Date startTime, Date endTime) {
|
|
||||||
int count = 0;
|
|
||||||
for (BilibiliLiveData liveData : liveDataDao.queryTimeOfRoomid(roomId, giftId, startTime, endTime)) {
|
|
||||||
count += liveData.getGiftindex() == null ? 0 : liveData.getGiftindex();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Integer> queryGiftSize(int roomId, Date startTime, Date endTime) {
|
|
||||||
Map<String, Integer> map = new HashMap<>();
|
|
||||||
List<BilibiliLiveData> list = liveDataDao.queryTimeOfRoomid(roomId, -1, startTime, endTime);
|
|
||||||
for (BilibiliLiveData liveData : list) {
|
|
||||||
if (map.containsKey(liveData.getGiftname())) {
|
|
||||||
map.put(liveData.getGiftname(), map.get(liveData.getGiftname()) + (liveData.getGiftindex() == null ? 0 : liveData.getGiftindex()));
|
|
||||||
} else {
|
|
||||||
map.put(liveData.getGiftname(), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int queryPriceSize(int roomId, Date startTime, Date endTime) {
|
|
||||||
int count = 0;
|
|
||||||
for (BilibiliLiveData liveData : liveDataDao.queryTimeOfRoomid(roomId, -1, startTime, endTime)) {
|
|
||||||
count += liveData.getPrice() == null ? 0 : liveData.getPrice();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BilibiliLiveData queryGiftOfId(int giftId) {
|
|
||||||
BilibiliLiveDataExample example = new BilibiliLiveDataExample();
|
|
||||||
example.createCriteria().andGiftidEqualTo(giftId);
|
|
||||||
List<BilibiliLiveData> list = liveDataDao.selectByExample(example);
|
|
||||||
if (list.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return list.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int queryGiftUserToDistinct(BilibiliUpInfo upData, Date startTime, Date endTime, String[] type) {
|
|
||||||
return liveDataDao.queryGiftUserToDistinct(upData.getRoomid(), -1, startTime, endTime, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int queryPopularCount(BilibiliUpInfo upData, Date startTime, Date endTime) {
|
|
||||||
int count = 0;
|
|
||||||
for (BilibiliLiveInfo info : liveInfoDao.queryTimeOfRoomid(upData.getRoomid(), startTime, endTime)) {
|
|
||||||
count += info.getPopular();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int queryUserCount(BilibiliUpInfo upData, Date startTime, Date endTime) {
|
|
||||||
int count = 0;
|
|
||||||
for (BilibiliLiveInfo info : liveInfoDao.queryTimeOfRoomid(upData.getRoomid(), startTime, endTime)) {
|
|
||||||
count += (info.getUserindex() + info.getVipuserindex());
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Integer> queryUserGiftCount(BilibiliUpInfo upData, Date startTime, Date endTime) {
|
|
||||||
Map<String, Integer> map = new HashMap<>();
|
|
||||||
List<BilibiliLiveInfo> list = liveInfoDao.queryTimeOfRoomid(upData.getRoomid(), startTime, endTime);
|
|
||||||
for (BilibiliLiveInfo info : list) {
|
|
||||||
map.put(new SimpleDateFormat("HH").format(info.getSubtime()), info.getGiftuser() == null ? 0 : info.getGiftuser());
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<BilibiliLiveInfo> queryLiveInfo(BilibiliUpInfo upInfo, Date startTime, Date endTime) {
|
|
||||||
return liveInfoDao.queryTimeOfRoomid(upInfo.getRoomid(), startTime, endTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, BigDecimal>> queryTimeGroup(int roomId, Date startTime, Date endTime) {
|
|
||||||
return liveDataDao.queryPriceTimeGroup(roomId, startTime, endTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, BigDecimal>> queryGiftTimeGroup(int roomId, Date startTime, Date endTime) {
|
|
||||||
return liveDataDao.queryGiftTimeGroup(roomId, startTime, endTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLive() {
|
|
||||||
String flag = configService.getConfig(Config.BILI_LIVE_FLAG);
|
|
||||||
if (flag != null) {
|
|
||||||
return !"0".equals(flag);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Tools;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.BiliBiliUpData;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import com.yutou.bilibili.sqlite.BiliBiliLiveDatabasesManager;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
public class BiliTools {
|
|
||||||
public static BilibiliUpInfo checkout(BilibiliUpInfo info) {
|
|
||||||
if (StringUtils.isEmpty(info.getUrl())) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!info.getUrl().contains("http")) {
|
|
||||||
info.setUrl("https://live.bilibili.com/" + info.getUrl());
|
|
||||||
}
|
|
||||||
BilibiliUpInfo data = getBiliUpInfo(info.getUrl());
|
|
||||||
info.setUrl(data.getUrl());
|
|
||||||
info.setRoomid(data.getRoomid());
|
|
||||||
info.setName(data.getName());
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BilibiliUpInfo getBiliUpInfo(String url) {
|
|
||||||
if(!url.startsWith("http")){
|
|
||||||
url="https://live.bilibili.com/"+url;
|
|
||||||
}
|
|
||||||
BilibiliUpInfo upData = new BilibiliUpInfo();
|
|
||||||
JSONObject json = LiveUtils.http_get("https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=" + url.replace("https://live.bilibili.com/", "").split("\\?")[0]);
|
|
||||||
com.yutou.bilibili.Tools.Log.i(json);
|
|
||||||
String roomId = json.getJSONObject("data").getJSONObject("room_info").getInteger("room_id") + "";
|
|
||||||
String name = json.getJSONObject("data").getJSONObject("anchor_info").getJSONObject("base_info").getString("uname");
|
|
||||||
upData.setRoomid(Integer.parseInt(roomId));
|
|
||||||
upData.setName(name);
|
|
||||||
upData.setUrl(url);
|
|
||||||
upData.setMid(LiveUtils.getMid(upData.getRoomid()));
|
|
||||||
return upData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Tools;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import org.java_websocket.client.WebSocketClient;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Timer;
|
|
||||||
|
|
||||||
public class LiveT implements ApplicationContextAware {
|
|
||||||
private static ApplicationContext applicationContext = null;
|
|
||||||
|
|
||||||
IBiliBiliLiveService service;
|
|
||||||
|
|
||||||
|
|
||||||
public static List<LiveT> list=new ArrayList<>();
|
|
||||||
int v;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
com.yutou.bilibili.Tools.Log.i("初始化2");
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiveT() {
|
|
||||||
com.yutou.bilibili.Tools.Log.i("初始化");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(int a){
|
|
||||||
|
|
||||||
v=a;
|
|
||||||
BilibiliUpInfo info=new BilibiliUpInfo();
|
|
||||||
info.setRoomid(a);
|
|
||||||
info.setOfflinelistening(0);
|
|
||||||
info.setSavedanmu(0);
|
|
||||||
info.setEnable(0);
|
|
||||||
info.setLive(0);
|
|
||||||
info.setSavelive(0);
|
|
||||||
info.setName("a"+a);
|
|
||||||
info.setUrl("#");
|
|
||||||
service=getBean(IBiliBiliLiveService.class);
|
|
||||||
service.addUpInfo(info);
|
|
||||||
}
|
|
||||||
public int get(){
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
if(LiveT.applicationContext==null){
|
|
||||||
LiveT.applicationContext=applicationContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static <T> T getBean(Class<T> clazz){
|
|
||||||
return applicationContext.getBean(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
package com.yutou.bilibili.BiliBili.Tools;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.AppData;
|
|
||||||
import com.yutou.bilibili.BiliBili.Live;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.QQBot.QQBotManager;
|
|
||||||
import com.yutou.bilibili.Tools.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class SaveLive {
|
|
||||||
private static SaveLive live;
|
|
||||||
private final List<String> saveList = new ArrayList<>();
|
|
||||||
private final Map<Integer, DownloadThread> downloads = new HashMap<>();
|
|
||||||
private final Map<Integer, Timer> heartbeats = new HashMap<>();
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private SaveLive() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SaveLive getInstance() {
|
|
||||||
if (live == null) {
|
|
||||||
live = new SaveLive();
|
|
||||||
}
|
|
||||||
return live;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addLive(Live live) {
|
|
||||||
if (saveList.contains(live.getInfo().getRoomid() + "")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (live.geData().checkLiveStatus() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
start(live.getInfo().getRoomid());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startLive(int roomId) {
|
|
||||||
start(roomId);
|
|
||||||
saveList.add(roomId + "");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean checkLive(int roomId) {
|
|
||||||
return saveList.contains(roomId + "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getLiveFile(int roomId) {
|
|
||||||
return downloads.get(roomId).liveFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long timer = 0;
|
|
||||||
|
|
||||||
public void stop(int roomId) {
|
|
||||||
com.yutou.bilibili.Tools.Log.i("t停止录播:" + roomId + " time=" + (System.currentTimeMillis() - timer));
|
|
||||||
saveList.remove(roomId + "");
|
|
||||||
|
|
||||||
if (downloads.containsKey(roomId)) {
|
|
||||||
downloads.get(roomId).isSave = false;
|
|
||||||
downloads.remove(roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heartbeats.containsKey(roomId)) {
|
|
||||||
heartbeats.get(roomId).cancel();
|
|
||||||
heartbeats.remove(roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void start(int roomId) {
|
|
||||||
if (checkLive(roomId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
timer = System.currentTimeMillis();
|
|
||||||
DownloadThread thread = new DownloadThread(roomId);
|
|
||||||
downloads.put(roomId, thread);
|
|
||||||
saveList.add(roomId + "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getLiveList() {
|
|
||||||
return saveList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DownloadThread extends Thread {
|
|
||||||
int roomId = 0;
|
|
||||||
boolean isSave = true;
|
|
||||||
Timer heartbeat;
|
|
||||||
File liveFile;
|
|
||||||
|
|
||||||
public DownloadThread(int roomId) {
|
|
||||||
this.roomId = roomId;
|
|
||||||
isSave = true;
|
|
||||||
|
|
||||||
start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getLiveUrl(int roomId) {
|
|
||||||
JSONObject json = LiveUtils.http_get(String.format("https://api.live.bilibili.com/xlive/web-room/v1/playUrl/playUrl?cid=%d&platform=web", roomId));
|
|
||||||
if (json != null && json.getInteger("code") == 0) {
|
|
||||||
return json.getJSONObject("data").getJSONArray("durl").getJSONObject(0).getString("url");
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
super.run();
|
|
||||||
String url = getLiveUrl(roomId);
|
|
||||||
try {
|
|
||||||
if (AppData.LIVE_SAVE_FFMPEG) {
|
|
||||||
ffmpegDownload(url);
|
|
||||||
} else {
|
|
||||||
httpDownload(url);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
if (!(e instanceof FileNotFoundException)) {
|
|
||||||
Log.i("录制发生意外:" + e.getMessage());
|
|
||||||
QQBotManager.getInstance().sendMessage("录制发生意外:" + e.getLocalizedMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SaveLive.this.stop(roomId);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ffmpegDownload(String url) throws Exception {
|
|
||||||
liveFile = new File(String.format("%slive%s%s%s[%s]%d.mp4",
|
|
||||||
ConfigTools.load(ConfigTools.CONFIG, "liveSavePath"),
|
|
||||||
File.separator,
|
|
||||||
AppTools.getToDayTime(),
|
|
||||||
File.separator,
|
|
||||||
AppTools.getToDayNowTimeToString().replace(":", ""),
|
|
||||||
roomId));
|
|
||||||
if (!liveFile.exists()) {
|
|
||||||
liveFile.mkdirs();
|
|
||||||
liveFile.delete();
|
|
||||||
}
|
|
||||||
String exec = String.format("%s -user_agent \"%s\" -cookies \"%s\" -headers \"%s\" -i \"%s\" -threads 8 -c:v copy -y \"%s\" %s ",
|
|
||||||
AppData.FFMPEG,
|
|
||||||
AppData.BILIBILI_HEADERS,
|
|
||||||
LiveUtils.getCookie(),
|
|
||||||
"Referer:https://live.bilibili.com",
|
|
||||||
url,
|
|
||||||
liveFile.getAbsolutePath(),
|
|
||||||
""
|
|
||||||
);
|
|
||||||
System.out.println(exec);
|
|
||||||
boolean isPrint = false;
|
|
||||||
Process process = AppTools.exec(exec);
|
|
||||||
InputStream inputStream = process.getErrorStream();
|
|
||||||
byte[] bytes = new byte[2048];
|
|
||||||
while (inputStream.read(bytes) > -1 && isSave) {
|
|
||||||
//System.out.println(new String(bytes,StandardCharsets.UTF_8));
|
|
||||||
if (!isPrint) {
|
|
||||||
com.yutou.bilibili.Tools.Log.i("开始录制:" + roomId);
|
|
||||||
QQBotManager.getInstance().sendMessage(roomId + " 已启动录制");
|
|
||||||
isPrint = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
process.destroy();
|
|
||||||
System.out.println("----------------stop ffmpeg");
|
|
||||||
inputStream.close();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("录制完成:" + roomId);
|
|
||||||
QQBotManager.getInstance().sendMessage("录制完成:" + roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void httpDownload(String url) throws Exception {
|
|
||||||
HttpURLConnection connection = LiveUtils.getBiliHttpGet(url, LiveUtils.getCookie());
|
|
||||||
connection.setReadTimeout(5000);
|
|
||||||
connection.setConnectTimeout(5000);
|
|
||||||
heartbeat = new Timer();
|
|
||||||
//Heartbeat beat = new Heartbeat();
|
|
||||||
heartbeat.schedule(new Heartbeat(), 0, 30000);
|
|
||||||
heartbeats.put(roomId, heartbeat);
|
|
||||||
//heartbeats.add(beat);
|
|
||||||
InputStream inputStream = connection.getInputStream();
|
|
||||||
liveFile = new File(String.format("%slive%s%s%s[%s]%d.mp4",
|
|
||||||
ConfigTools.load(ConfigTools.CONFIG, "liveSavePath"),
|
|
||||||
File.separator,
|
|
||||||
AppTools.getToDayTime(),
|
|
||||||
File.separator,
|
|
||||||
AppTools.getToDayNowTimeToString().replace(":", ""),
|
|
||||||
roomId));
|
|
||||||
if (!liveFile.exists()) {
|
|
||||||
liveFile.mkdirs();
|
|
||||||
liveFile.delete();
|
|
||||||
}
|
|
||||||
boolean isPrint = false;
|
|
||||||
FileOutputStream outputStream = new FileOutputStream(liveFile);
|
|
||||||
int len;
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
while ((len = inputStream.read(bytes)) != -1 && isSave) {
|
|
||||||
outputStream.write(bytes, 0, len);
|
|
||||||
outputStream.flush();
|
|
||||||
if (!isPrint) {
|
|
||||||
com.yutou.bilibili.Tools.Log.i("开始录制:" + roomId);
|
|
||||||
QQBotManager.getInstance().sendMessage(roomId + " 已启动录制");
|
|
||||||
isPrint = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outputStream.close();
|
|
||||||
inputStream.close();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("录制完成:" + roomId + " save = " + isSave + " len = " + len);
|
|
||||||
QQBotManager.getInstance().sendMessage("录制完成:" + roomId + " save = " + isSave + " len = " + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Heartbeat extends TimerTask {
|
|
||||||
int nextInterval = 1;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
JSONObject hearBeat;
|
|
||||||
JSONObject userHear = new JSONObject();
|
|
||||||
JSONObject cookie = JSONObject.parseObject(LiveUtils.getFile("cookies.json"));
|
|
||||||
hearBeat = LiveUtils.http_get("https://api.live.bilibili.com/relation/v1/Feed/heartBeat");
|
|
||||||
com.yutou.bilibili.Tools.Log.i(hearBeat + " \t");
|
|
||||||
hearBeat = LiveUtils.http_get(String.format("https://live-trace.bilibili.com/xlive/rdata-interface/v1/heartbeat/webHeartBeat?hb=%s&pf=web", URLEncoder.encode(new String(Base64.getEncoder().encode(String.format("%d|%d|1|0", nextInterval, roomId).getBytes(StandardCharsets.UTF_8))), "UTF-8")));
|
|
||||||
com.yutou.bilibili.Tools.Log.i(hearBeat + "\t");
|
|
||||||
nextInterval = hearBeat.getJSONObject("data").getInteger("next_interval");
|
|
||||||
com.yutou.bilibili.Tools.Log.i("next = " + nextInterval);
|
|
||||||
userHear.put("csrf_token", cookie.getString("bili_jct"));
|
|
||||||
userHear.put("csrf", cookie.getString("bili_jct"));
|
|
||||||
userHear.put("visit_id", "");
|
|
||||||
hearBeat = LiveUtils.http_post("https://api.live.bilibili.com/User/userOnlineHeart", HttpTools.toUrlParams(userHear));
|
|
||||||
com.yutou.bilibili.Tools.Log.i("[" + AppTools.getToDayNowTimeToString() + "]" + hearBeat);
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.yutou.bilibili;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Live;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.LiveT;
|
|
||||||
import com.yutou.bilibili.QQBot.QQBotManager;
|
|
||||||
import com.yutou.bilibili.Tools.ExcelUtils;
|
|
||||||
import com.yutou.bilibili.Tools.ServiceTools;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
|
|
||||||
@Import({Live.class,ServiceTools.class, ExcelUtils.class, QQBotManager.class})
|
|
||||||
@SpringBootApplication
|
|
||||||
public class BilibiliApplication {
|
|
||||||
|
|
||||||
public static String version="0.8.4";
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
QQBotManager.getInstance().init();
|
|
||||||
SpringApplication.run(BilibiliApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package com.yutou.bilibili.Controllers;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
|
||||||
|
import com.yutou.bilibili.datas.ResultData;
|
||||||
|
import com.yutou.bilibili.datas.ReturnCode;
|
||||||
|
import com.yutou.bilibili.services.LiveConfigService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/live/config/")
|
||||||
|
public class LiveConfigController {
|
||||||
|
@Resource
|
||||||
|
LiveConfigService configService;
|
||||||
|
|
||||||
|
@RequestMapping(value = "set", method = RequestMethod.POST)
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject setConfig(String url, LiveConfigDatabaseBean bean) {
|
||||||
|
LiveConfigDatabaseBean config = configService.addConfig(url, bean);
|
||||||
|
if (config != null) {
|
||||||
|
return ResultData.success(config.toJson());
|
||||||
|
}
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "update", method = RequestMethod.POST)
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject updateConfig(String roomId, LiveConfigDatabaseBean bean) {
|
||||||
|
LiveConfigDatabaseBean config = configService.updateConfig(new BigInteger(roomId), bean);
|
||||||
|
if (config != null) {
|
||||||
|
return ResultData.success(config.toJson());
|
||||||
|
}
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "get", method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject getConfig(String roomId) {
|
||||||
|
if ("0".equals(roomId) || !StringUtils.hasText(roomId)) {
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
LiveConfigDatabaseBean config = configService.getConfig(new BigInteger(roomId));
|
||||||
|
if (config != null) {
|
||||||
|
return ResultData.success(config.toJson());
|
||||||
|
}
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "all", method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject getAllConfig() {
|
||||||
|
List<LiveConfigDatabaseBean> config = configService.getAllConfig();
|
||||||
|
if (config != null) {
|
||||||
|
return ResultData.success(JSONArray.parseArray(JSONArray.toJSONString(config)));
|
||||||
|
}
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "delete", method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject deleteConfig(BigInteger roomId) {
|
||||||
|
if (roomId.equals(BigInteger.ZERO)) {
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
boolean flag = configService.deleteConfig(roomId);
|
||||||
|
if (flag) {
|
||||||
|
return ResultData.success(ReturnCode.RC100);
|
||||||
|
}
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.yutou.bilibili.Controllers;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.biliapi.bean.live.LiveRoomConfig;
|
||||||
|
import com.yutou.biliapi.net.WebSocketManager;
|
||||||
|
import com.yutou.bilibili.datas.ResultData;
|
||||||
|
import com.yutou.bilibili.datas.ReturnCode;
|
||||||
|
import com.yutou.bilibili.services.LiveDanmuService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class LiveDanmuController {
|
||||||
|
@Resource
|
||||||
|
LiveDanmuService service;
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping("/live/danmu/list")
|
||||||
|
public JSONObject getLiveDanmuList() {
|
||||||
|
return ResultData.success(service.getLiveRoomList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping("/live/danmu/stop")
|
||||||
|
public JSONObject stopLiveDanmu(String roomId) {
|
||||||
|
service.stop(roomId);
|
||||||
|
return ResultData.success(ReturnCode.RC100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping("/live/danmu/start")
|
||||||
|
public JSONObject startLiveDanmu(String roomId) {
|
||||||
|
service.start(roomId);
|
||||||
|
return ResultData.success(ReturnCode.RC100);
|
||||||
|
}
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping("/live/danmu/file/list")
|
||||||
|
public JSONObject getDanmuList(String roomId) {
|
||||||
|
return ResultData.success(service.getDanmuFileList(roomId));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.yutou.bilibili.Controllers;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.biliapi.bean.live.database.LiveConfigDatabaseBean;
|
||||||
|
import com.yutou.biliapi.databases.BiliLiveConfigDatabase;
|
||||||
|
import com.yutou.biliapi.net.WebSocketManager;
|
||||||
|
import com.yutou.bilibili.datas.ResultData;
|
||||||
|
import com.yutou.bilibili.datas.ReturnCode;
|
||||||
|
import com.yutou.bilibili.services.LiveVideoService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class LiveVideoController {
|
||||||
|
@Resource
|
||||||
|
LiveVideoService videoService;
|
||||||
|
|
||||||
|
@RequestMapping("/live/video/list")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject getLiveVideoList() {
|
||||||
|
return ResultData.success(videoService.getDownloadTasks());
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/live/video/stop")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject stopDownload(String roomId) {
|
||||||
|
videoService.stop(roomId, true);
|
||||||
|
return ResultData.success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/live/video/start")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject startDownload(String roomId) {
|
||||||
|
BiliLiveConfigDatabase liveConfigDatabase = new BiliLiveConfigDatabase();
|
||||||
|
List<LiveConfigDatabaseBean> list = liveConfigDatabase.getAllConfig();
|
||||||
|
for (LiveConfigDatabaseBean bean : list) {
|
||||||
|
if (bean.getRoomId().toString().equals(roomId)) {
|
||||||
|
videoService.start(bean, true);
|
||||||
|
return ResultData.success(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ResultData.fail(ReturnCode.RC999);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
package com.yutou.bilibili.Controllers;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.AppData;
|
|
||||||
import com.yutou.bilibili.QQBot.QQBotManager;
|
|
||||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
|
||||||
import com.yutou.bilibili.Tools.Config;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class SystemConfigController {
|
|
||||||
@Resource
|
|
||||||
ISystemConfigService configService;
|
|
||||||
|
|
||||||
@RequestMapping("/system/get/config.do")
|
|
||||||
@ResponseBody
|
|
||||||
public JSONObject getRegUser() {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
String reg = configService.getConfig(Config.USER_REG);
|
|
||||||
String bLive = configService.getConfig(Config.BILI_LIVE_FLAG);
|
|
||||||
if (reg == null) {
|
|
||||||
reg = "0";
|
|
||||||
}
|
|
||||||
if (bLive == null) {
|
|
||||||
bLive = "0";
|
|
||||||
}
|
|
||||||
data.put(Config.USER_REG, reg);
|
|
||||||
data.put(Config.BILI_LIVE_FLAG, bLive);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("data", data);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/system/set/config.do")
|
|
||||||
@ResponseBody
|
|
||||||
public JSONObject setConfig(String key, String value) {
|
|
||||||
configService.setConfig(key, value);
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "ok");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/system/public/reg.do")
|
|
||||||
@ResponseBody
|
|
||||||
public JSONObject getRegModel() {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
String reg = configService.getConfig(Config.USER_REG);
|
|
||||||
boolean model = false;
|
|
||||||
if (reg == null) {
|
|
||||||
reg = "0";
|
|
||||||
}
|
|
||||||
if (reg.equals("1")) {
|
|
||||||
model = true;
|
|
||||||
}
|
|
||||||
data.put(Config.USER_REG, model);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("data", data);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/system/set/ffmpeg.do")
|
|
||||||
public JSONObject setFFmpeg(String ffmpeg) throws UnsupportedEncodingException {
|
|
||||||
ffmpeg = URLDecoder.decode(ffmpeg, "UTF-8");
|
|
||||||
configService.setConfig(Config.SYSTEM_VIDEO_FFMPEG, ffmpeg);
|
|
||||||
AppData.FFMPEG = ffmpeg;
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "ok");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/system/get/ffmpeg.do")
|
|
||||||
public JSONObject getFFmpeg() {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
String reg = configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG);
|
|
||||||
data.put(Config.SYSTEM_VIDEO_FFMPEG, reg);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("data", data);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/system/set/savelive.do")
|
|
||||||
public JSONObject setSaveLive(String model) throws UnsupportedEncodingException {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
if (StringUtils.isEmpty(configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG))) {
|
|
||||||
json.put("code", 404);
|
|
||||||
json.put("msg", "请先设置FFmpeg路径");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
model = URLDecoder.decode(model, "UTF-8");
|
|
||||||
configService.setConfig(Config.SYSTEM_VIDEO_SAVE_MODEL, model);
|
|
||||||
AppData.LIVE_SAVE_FFMPEG = model.equals("ffmpeg");
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "ok");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/system/get/savelive.do")
|
|
||||||
public JSONObject getSaveLiveModel() {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
JSONObject data = new JSONObject();
|
|
||||||
String reg = configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL);
|
|
||||||
System.out.println(reg);
|
|
||||||
data.put(Config.SYSTEM_VIDEO_SAVE_MODEL, (!StringUtils.isEmpty(reg) && reg.equals("ffmpeg")));
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("data", data);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/system/qq/login.do")
|
|
||||||
public JSONObject loginQQ() {
|
|
||||||
QQBotManager.getInstance().stop();
|
|
||||||
QQBotManager.getInstance().init();
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "ok");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.yutou.bilibili.Controllers;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class TestControllers {
|
||||||
|
@RequestMapping("/root/test")
|
||||||
|
@ResponseBody
|
||||||
|
public String test(){
|
||||||
|
return "hello world";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
package com.yutou.bilibili.Controllers;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.BiliTools;
|
|
||||||
import com.yutou.bilibili.Services.IUserService;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.Tools.Config;
|
|
||||||
import com.yutou.bilibili.Tools.RedisTools;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UBiliUp;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUser;
|
|
||||||
import org.apache.tomcat.util.security.MD5Encoder;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class UserController {
|
|
||||||
@Resource
|
|
||||||
IUserService service;
|
|
||||||
@Resource
|
|
||||||
IBiliBiliLiveService biliService;
|
|
||||||
@Resource
|
|
||||||
ISystemConfigService configService;
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/user/reg.do")
|
|
||||||
public JSONObject reg(UUser user, HttpServletResponse response) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
String isReg = configService.getConfig(Config.USER_REG);
|
|
||||||
if (isReg != null) {
|
|
||||||
if (isReg.equals("0")) {
|
|
||||||
json.put("code", -2);
|
|
||||||
json.put("msg", "当前系统禁止注册");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
user.setPower("[1,2,3,5,6,7]");
|
|
||||||
user.setSubtime(new Date());
|
|
||||||
user.setLogintoken(UUID.randomUUID().toString());
|
|
||||||
RedisTools.set(user.getLogintoken(),user.getId()+"",30*24*60);
|
|
||||||
AppTools.setCookie(response, "login", user.getLogintoken(), -1);
|
|
||||||
boolean flag = service.reg(user);
|
|
||||||
if (flag) {
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "注册成功");
|
|
||||||
} else {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "该用户已存在或无法注册");
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/user/login.do")
|
|
||||||
public JSONObject login(UUser user, HttpServletResponse response) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("code", 0);
|
|
||||||
if (service.login(user.getUser(), user.getPassword())) {
|
|
||||||
user = service.getUser(user.getUser());
|
|
||||||
//user.setLogintoken(UUID.randomUUID().toString());
|
|
||||||
RedisTools.set(user.getLogintoken(),user.getId()+"",30*24*60);
|
|
||||||
AppTools.setCookie(response, "login", user.getLogintoken(), -1);
|
|
||||||
json.put("msg", "登陆成功");
|
|
||||||
json.put("power", user.getPower());
|
|
||||||
} else {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "登陆失败");
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/user/logout.do")
|
|
||||||
public JSONObject logout(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
String token = AppTools.getLoginToken(request);
|
|
||||||
if (StringUtils.isEmpty(token)) {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "注销失败");
|
|
||||||
} else {
|
|
||||||
UUser user = service.getUserToToken(token);
|
|
||||||
if (user != null) {
|
|
||||||
RedisTools.remove(user.getLogintoken());
|
|
||||||
user.setLogintoken("");
|
|
||||||
service.update(user);
|
|
||||||
AppTools.deleteCookie(request, response, "login");
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "注销成功");
|
|
||||||
} else {
|
|
||||||
json.put("code", -2);
|
|
||||||
json.put("msg", "注销失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/user/set/update.do")
|
|
||||||
public JSONObject update(UUser user, HttpServletRequest request) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
String token = AppTools.getLoginToken(request);
|
|
||||||
if (StringUtils.isEmpty(token)) {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "未登录");
|
|
||||||
} else {
|
|
||||||
UUser loginUser = service.getUserToUid(Integer.parseInt(RedisTools.get(token)));
|
|
||||||
if (loginUser != null) {
|
|
||||||
user.setLogintoken("");
|
|
||||||
user.setId(loginUser.getId());
|
|
||||||
user.setPower(loginUser.getPower());
|
|
||||||
user.setBiliCookie(loginUser.getBiliCookie());
|
|
||||||
user.setSubtime(loginUser.getSubtime());
|
|
||||||
user.setPassword(AppTools.getMD5 (user.getPassword()));
|
|
||||||
service.update(user);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "修改成功");
|
|
||||||
} else {
|
|
||||||
json.put("code", -2);
|
|
||||||
json.put("msg", "修改失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/user/up/list.do")
|
|
||||||
public JSONObject uplist(HttpServletRequest request) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
String token = AppTools.getLoginToken(request);
|
|
||||||
if (StringUtils.isEmpty(token)) {
|
|
||||||
json.put("code", "-1");
|
|
||||||
json.put("msg", "未登录");
|
|
||||||
} else {
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", "ok");
|
|
||||||
json.put("data", service.getUserUp(Integer.parseInt(RedisTools.get(token))));
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/user/up/set/add.do")
|
|
||||||
public JSONObject addUp(HttpServletRequest request, BilibiliUpInfo info) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
String token = AppTools.getLoginToken(request);
|
|
||||||
if (StringUtils.isEmpty(token)) {
|
|
||||||
json.put("code", "-1");
|
|
||||||
json.put("msg", "未登录");
|
|
||||||
} else {
|
|
||||||
int roomid = 0;
|
|
||||||
if (!info.getUrl().startsWith("http")) {
|
|
||||||
info.setUrl("https://live.bilibili.com/" + info.getUrl());
|
|
||||||
}
|
|
||||||
BilibiliUpInfo tmp = biliService.queryUpToUrl(info.getUrl());
|
|
||||||
if (tmp == null) {
|
|
||||||
info = BiliTools.checkout(info);
|
|
||||||
if (info != null) {
|
|
||||||
roomid = info.getRoomid();
|
|
||||||
info.setEnable(0);
|
|
||||||
biliService.addUpInfo(info);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
roomid = tmp.getRoomid();
|
|
||||||
}
|
|
||||||
if (roomid == 0) {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "添加失败");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
UBiliUp up = new UBiliUp();
|
|
||||||
up.setUid(Integer.parseInt(RedisTools.get(token)));
|
|
||||||
up.setRoomid(roomid);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("msg", service.addUp(up) ? "添加成功" : "添加失败");
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ResponseBody
|
|
||||||
@RequestMapping("/user/get/test.do")
|
|
||||||
public JSONObject testUser(HttpServletRequest request) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
String token = AppTools.getLoginToken(request);
|
|
||||||
if (StringUtils.isEmpty(token)) {
|
|
||||||
json.put("code", -1);
|
|
||||||
json.put("msg", "未登录");
|
|
||||||
} else {
|
|
||||||
UUser user = service.getUserToUid(Integer.parseInt(RedisTools.get(token)));;
|
|
||||||
if (user == null) {
|
|
||||||
json.put("code", -2);
|
|
||||||
json.put("msg", "未登录");
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
JSONArray powers = JSONArray.parseArray(user.getPower());
|
|
||||||
JSONObject ujson = (JSONObject) JSON.toJSON(user);
|
|
||||||
ujson.remove("logintoken");
|
|
||||||
ujson.remove("biliCookie");
|
|
||||||
ujson.remove("password");
|
|
||||||
ujson.remove("subtime");
|
|
||||||
ujson.put("power", powers);
|
|
||||||
json.put("code", 0);
|
|
||||||
json.put("data", ujson);
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.yutou.bilibili.Controllers;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.yutou.bilibili.Tools.FileServerUtils;
|
||||||
|
import com.yutou.bilibili.Tools.Tools;
|
||||||
|
import com.yutou.bilibili.datas.ResultData;
|
||||||
|
import com.yutou.bilibili.datas.VideoFilePath;
|
||||||
|
import com.yutou.bilibili.services.LiveVideoService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.core.io.FileSystemResource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class VideoFileController {
|
||||||
|
@Resource
|
||||||
|
LiveVideoService videoService;
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@RequestMapping("/file/list")
|
||||||
|
public JSONObject getFileList(String roomId) {
|
||||||
|
List<VideoFilePath> list;
|
||||||
|
if (StringUtils.hasText(roomId)) {
|
||||||
|
list = videoService.getVideoPath(roomId);
|
||||||
|
} else {
|
||||||
|
list = videoService.getAllVideoPath();
|
||||||
|
}
|
||||||
|
return ResultData.success(list);
|
||||||
|
}
|
||||||
|
@RequestMapping("/file/{base64}")
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity<FileSystemResource> getFile(@PathVariable String base64) {
|
||||||
|
File file = FileServerUtils.toFile(base64);
|
||||||
|
System.out.println(file.getAbsolutePath());
|
||||||
|
return Tools.getFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,449 +0,0 @@
|
|||||||
package com.yutou.bilibili.QQBot;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Controllers.RealTimeDataController;
|
|
||||||
import com.yutou.bilibili.BiliBili.Live;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
|
|
||||||
import com.yutou.bilibili.BilibiliApplication;
|
|
||||||
import com.yutou.bilibili.Tools.*;
|
|
||||||
import com.yutou.bilibili.interfaces.DownloadInterface;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import kotlin.coroutines.CoroutineContext;
|
|
||||||
import net.mamoe.mirai.Bot;
|
|
||||||
import net.mamoe.mirai.BotFactory;
|
|
||||||
import net.mamoe.mirai.event.EventHandler;
|
|
||||||
import net.mamoe.mirai.event.GlobalEventChannel;
|
|
||||||
import net.mamoe.mirai.event.ListeningStatus;
|
|
||||||
import net.mamoe.mirai.event.SimpleListenerHost;
|
|
||||||
import net.mamoe.mirai.event.events.GroupMessageEvent;
|
|
||||||
import net.mamoe.mirai.event.events.MessageEvent;
|
|
||||||
import net.mamoe.mirai.message.data.Image;
|
|
||||||
import net.mamoe.mirai.message.data.MessageChainBuilder;
|
|
||||||
import net.mamoe.mirai.utils.BotConfiguration;
|
|
||||||
import net.mamoe.mirai.utils.ExternalResource;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class QQBotManager implements ApplicationContextAware {
|
|
||||||
private static ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
if (QQBotManager.applicationContext == null) {
|
|
||||||
QQBotManager.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T getBean(Class<T> tClass) {
|
|
||||||
return applicationContext.getBean(tClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class QQCommands {
|
|
||||||
private final static String QQ_HELP = "!help";
|
|
||||||
private final static String QQ_SYSTEM_LOG = "!log";
|
|
||||||
private final static String QQ_SYSTEM_RESTART = "!restart";
|
|
||||||
private final static String QQ_GET_IP = "!ip";
|
|
||||||
private final static String QQ_GET_VERSION = "!version";
|
|
||||||
private final static String QQ_LIVE_LIST = "!列表";
|
|
||||||
private final static String QQ_LIVE_SAVE = "!录播列表";
|
|
||||||
private final static String QQ_LIVE_TO_DAY_DATE = "!今日数据";
|
|
||||||
private final static String QQ_LIVE_DATE = "!数据";
|
|
||||||
private final static String QQ_LIVE_USE_SAVE = "!启动录播";
|
|
||||||
private final static String QQ_LIVE_RELINK="!relink";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static QQBotManager botManager = null;
|
|
||||||
private Bot bot;
|
|
||||||
private static long qqGroup;
|
|
||||||
private boolean isLogin = false;
|
|
||||||
private static boolean isInit = false;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
RealTimeDataController realTimeDataController;
|
|
||||||
|
|
||||||
|
|
||||||
private QQBotManager() {
|
|
||||||
qqGroup = ConfigTools.load(ConfigTools.CONFIG, "qq_group",long.class,950075833L);
|
|
||||||
}
|
|
||||||
public void stop(){
|
|
||||||
if(bot!=null){
|
|
||||||
bot.close();
|
|
||||||
bot=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void init() {
|
|
||||||
if (!ConfigTools.load(ConfigTools.CONFIG, "qq_bot",boolean.class)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
new Thread(() -> {
|
|
||||||
long qq = Long.parseLong((String) ConfigTools.load(ConfigTools.CONFIG, "qq_number"));
|
|
||||||
String password = (String) ConfigTools.load(ConfigTools.CONFIG, "qq_password");
|
|
||||||
bot = BotFactory.INSTANCE.newBot(qq, password, new BotConfiguration() {
|
|
||||||
{
|
|
||||||
setProtocol(MiraiProtocol.ANDROID_PAD);
|
|
||||||
fileBasedDeviceInfo("qq_bot_devices_info.json");
|
|
||||||
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "qq_debug"))) {
|
|
||||||
noBotLog();
|
|
||||||
noNetworkLog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//Events.registerEvents(bot, new MessageListener());
|
|
||||||
GlobalEventChannel.INSTANCE.registerListenerHost(new MessageListener());
|
|
||||||
Log.i("准备登陆");
|
|
||||||
bot.login();
|
|
||||||
Log.i("登陆成功");
|
|
||||||
isLogin = true;
|
|
||||||
isInit = true;
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Log.e(e);
|
|
||||||
}
|
|
||||||
String str = sendMessage("姬妻酱上线拉~");
|
|
||||||
Log.i(str);
|
|
||||||
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
bot.join();
|
|
||||||
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static QQBotManager getInstance() {
|
|
||||||
if (botManager == null && !isInit) {
|
|
||||||
botManager = new QQBotManager();
|
|
||||||
}
|
|
||||||
return botManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLogin() {
|
|
||||||
return isLogin;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Image getImage(File file) {
|
|
||||||
if (bot != null) {
|
|
||||||
ExternalResource resource=ExternalResource.create(file);
|
|
||||||
Image image;
|
|
||||||
image= Objects.requireNonNull(bot.getGroup(qqGroup)).uploadImage(resource);
|
|
||||||
try {
|
|
||||||
resource.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getNotLoginQQ() {
|
|
||||||
return "没有登录QQ";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String sendMessage(String text) {
|
|
||||||
if (bot != null) {
|
|
||||||
try {
|
|
||||||
return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(text).toString();
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getNotLoginQQ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String sendMessage(Long group, String text) {
|
|
||||||
if (bot != null) {
|
|
||||||
try {
|
|
||||||
return Objects.requireNonNull(bot.getGroup(group)).sendMessage(text).toString();
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getNotLoginQQ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendMessage(Long group, MessageChainBuilder builder) {
|
|
||||||
if (bot != null) {
|
|
||||||
Objects.requireNonNull(bot.getGroup(group)).sendMessage(builder.asMessageChain());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String sendMessage(File imageFile, String text) {
|
|
||||||
try {
|
|
||||||
if (bot != null) {
|
|
||||||
Image image = getImage(imageFile);
|
|
||||||
MessageChainBuilder builder = new MessageChainBuilder();
|
|
||||||
if (image != null) {
|
|
||||||
builder.append(image);
|
|
||||||
}
|
|
||||||
builder.append(text);
|
|
||||||
return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(builder.asMessageChain()).toString();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getNotLoginQQ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String sendMessage(List<File> imgs, String text) {
|
|
||||||
if (bot != null) {
|
|
||||||
MessageChainBuilder builder = new MessageChainBuilder();
|
|
||||||
for (File img : imgs) {
|
|
||||||
builder.append(Objects.requireNonNull(getImage(img)));
|
|
||||||
}
|
|
||||||
builder.append(text);
|
|
||||||
return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(builder.asMessageChain()).toString();
|
|
||||||
}
|
|
||||||
return getNotLoginQQ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<String> getImages(String str) {
|
|
||||||
List<String> list = new ArrayList<>();
|
|
||||||
String regex = "<img(.*?)/img>";
|
|
||||||
Pattern pattern = Pattern.compile(regex);
|
|
||||||
Matcher matcher = pattern.matcher(str);
|
|
||||||
while (matcher.find()) {
|
|
||||||
list.add(matcher.group().replace("<img", "")
|
|
||||||
.replace("/img>", "")
|
|
||||||
.trim());
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MessageListener extends SimpleListenerHost {
|
|
||||||
@Override
|
|
||||||
public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) {
|
|
||||||
// super.handleException(context, exception);
|
|
||||||
exception.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public ListeningStatus onMessage(MessageEvent event) {
|
|
||||||
String message=event.getMessage().contentToString();
|
|
||||||
String msg = message.replace("!", "!").toLowerCase();
|
|
||||||
msg=msg.trim();
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
JSONObject json;
|
|
||||||
String[] cmd = new String[0];
|
|
||||||
int _roomId = 0;
|
|
||||||
switch (msg) {
|
|
||||||
case QQCommands.QQ_GET_IP:
|
|
||||||
json = JSONObject.parseObject(HttpTools.get("https://api.asilu.com/ip/"));
|
|
||||||
String ip = json.getString("ip");
|
|
||||||
getInstance().sendMessage("服务器IP:" + ip);
|
|
||||||
break;
|
|
||||||
case QQCommands.QQ_GET_VERSION:
|
|
||||||
sendVersion();
|
|
||||||
break;
|
|
||||||
case QQCommands.QQ_SYSTEM_RESTART:
|
|
||||||
getInstance().sendMessage("正在重启服务");
|
|
||||||
System.out.println("结束进程");
|
|
||||||
try {
|
|
||||||
AppTools.exec("cd /home/yutou/public/servier/biliob && ./start.sh");
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QQCommands.QQ_LIVE_LIST:
|
|
||||||
builder.append("当前正在记录数据的直播间:");
|
|
||||||
builder.append("\n");
|
|
||||||
for (Live live : Live.lives.values()) {
|
|
||||||
Live.LiveInfo info=live.getLiveInfo();
|
|
||||||
if (live.geData().getLive()==1) {
|
|
||||||
builder.append("【直播中】");
|
|
||||||
}
|
|
||||||
builder
|
|
||||||
.append("名字:").append(live.geData().getName()).append(" ")
|
|
||||||
.append(" roomId:").append(live.geData().getRoomid()).append(" ");
|
|
||||||
if (info != null) {
|
|
||||||
builder.append("标题:").append(info.getTitle()).append("\n");
|
|
||||||
} else {
|
|
||||||
builder.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getInstance().sendMessage(builder.toString());
|
|
||||||
break;
|
|
||||||
case QQCommands.QQ_LIVE_SAVE:
|
|
||||||
builder.append("当前正在录制的直播间:");
|
|
||||||
builder.append("\n");
|
|
||||||
for (String roomId : SaveLive.getInstance().getLiveList()) {
|
|
||||||
BilibiliUpInfo data = new BilibiliUpInfo();
|
|
||||||
data.setRoomid(Integer.parseInt(roomId));
|
|
||||||
Live live = LiveUtils.liveContains(data);
|
|
||||||
if (live != null) {
|
|
||||||
File file = SaveLive.getInstance().getLiveFile(Integer.parseInt(roomId));
|
|
||||||
builder
|
|
||||||
.append("名字:").append(live.geData().getName()).append(" ")
|
|
||||||
.append("文件大小(字节):").append(file.length()).append(" ")
|
|
||||||
.append("roomId:").append(live.geData().getRoomid()).append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
getInstance().sendMessage(builder.toString());
|
|
||||||
break;
|
|
||||||
case QQCommands.QQ_HELP:
|
|
||||||
for (Field field : QQCommands.class.getDeclaredFields()) {
|
|
||||||
try {
|
|
||||||
field.setAccessible(true);
|
|
||||||
builder.append(field.get(null)).append("\n");
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getInstance().sendMessage(builder.toString());
|
|
||||||
break;
|
|
||||||
case QQCommands.QQ_LIVE_RELINK:
|
|
||||||
for (Live live : Live.lives.values()) {
|
|
||||||
live.stop();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (msg.startsWith(QQCommands.QQ_LIVE_TO_DAY_DATE)) {
|
|
||||||
try {
|
|
||||||
cmd = msg.split(" ");
|
|
||||||
_roomId = Integer.parseInt(cmd[1]);
|
|
||||||
QQBotManager.getInstance().sendMessage("请稍等,正在查询...");
|
|
||||||
sendGiftData(_roomId, null, null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_TO_DAY_DATE + "+空格+roomId");
|
|
||||||
}
|
|
||||||
} else if (msg.startsWith(QQCommands.QQ_LIVE_DATE)) {
|
|
||||||
try {
|
|
||||||
cmd = msg.split(" ");
|
|
||||||
_roomId = Integer.parseInt(cmd[1]);
|
|
||||||
Date startTime = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").parse(cmd[2]);
|
|
||||||
Date endTime = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").parse(cmd[3]);
|
|
||||||
QQBotManager.getInstance().sendMessage("请稍等,正在查询...");
|
|
||||||
sendGiftData(_roomId, startTime, endTime);
|
|
||||||
} catch (Exception e) {
|
|
||||||
getInstance().sendMessage("参数错误。" +
|
|
||||||
"\n使用方式: " + QQCommands.QQ_LIVE_DATE + "+空格+roomId+起始时间+空格+结束时间" +
|
|
||||||
"\n时间格式:年-月-日_时:分:秒 例:2021-4-1_12:00:00" +
|
|
||||||
"\n时分秒不可省略");
|
|
||||||
}
|
|
||||||
} else if (msg.startsWith(QQCommands.QQ_LIVE_USE_SAVE)) {
|
|
||||||
try {
|
|
||||||
cmd = msg.split(" ");
|
|
||||||
_roomId = Integer.parseInt(cmd[1]);
|
|
||||||
if (SaveLive.getInstance().checkLive(_roomId)) {
|
|
||||||
SaveLive.getInstance().stop(_roomId);
|
|
||||||
}
|
|
||||||
SaveLive.getInstance().startLive(_roomId);
|
|
||||||
getInstance().sendMessage("已启动" + _roomId + "的录播");
|
|
||||||
} catch (Exception e) {
|
|
||||||
getInstance().sendMessage("参数错误。\n使用方式: " + QQCommands.QQ_LIVE_USE_SAVE + "+空格+roomId");
|
|
||||||
}
|
|
||||||
} else if (msg.startsWith(QQCommands.QQ_SYSTEM_LOG)) {
|
|
||||||
try {
|
|
||||||
cmd = message.replace("!","!").replace(QQCommands.QQ_SYSTEM_LOG,"").split(" ");
|
|
||||||
RedisTools.set(1,"live-log",cmd[1].trim());
|
|
||||||
getInstance().sendMessage("日志设为:"+cmd[1].trim());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
Log.i("未知指令:"+msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ListeningStatus.LISTENING; // 表示继续监听事件
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendGiftData(int roomId, Date startTime, Date endTime) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (startTime == null) {
|
|
||||||
startTime = AppTools.getToDayStartTime();
|
|
||||||
}
|
|
||||||
if (endTime == null) {
|
|
||||||
endTime = AppTools.getToDayNowTime();
|
|
||||||
}
|
|
||||||
if (getInstance().realTimeDataController == null) {
|
|
||||||
getInstance().realTimeDataController = getInstance().getBean(RealTimeDataController.class);
|
|
||||||
}
|
|
||||||
JSONObject json = getInstance().realTimeDataController.queryToDayLiveData(roomId, startTime, endTime);
|
|
||||||
System.out.println(json);
|
|
||||||
builder.append("当前人气:").append(json.getJSONObject("data").getInteger("popular")).append("\n");
|
|
||||||
builder.append("普通观众入场:").append(json.getJSONObject("data").getInteger("userLength")).append("\n");
|
|
||||||
builder.append("舰长入场:").append(json.getJSONObject("data").getInteger("vipLength")).append("\n");
|
|
||||||
int price = 0;
|
|
||||||
for (Object o : json.getJSONObject("data").getJSONArray("price")) {
|
|
||||||
price += ((JSONObject) o).getInteger("price");
|
|
||||||
}
|
|
||||||
builder.append("金瓜子:").append(price).append(" 抽成后:").append((price / 2) / 1000).append("¥").append("\n");
|
|
||||||
builder.append("礼物收益情况:").append("\n");
|
|
||||||
for (Object o : json.getJSONObject("data").getJSONArray("gift")) {
|
|
||||||
builder.append(((JSONObject) o).getString("giftName")).append(":").append(((JSONObject) o).getInteger("size")).append("\n");
|
|
||||||
}
|
|
||||||
getInstance().sendMessage(builder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<File> files;
|
|
||||||
private int index = 0;
|
|
||||||
|
|
||||||
private void sendImagesMsg(List<String> imgs, String text) {
|
|
||||||
files = new ArrayList<>();
|
|
||||||
index = 0;
|
|
||||||
if (imgs.size() == 0) {
|
|
||||||
getInstance().sendMessage(text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (String img : imgs) {
|
|
||||||
Tools.download(img, new DownloadInterface() {
|
|
||||||
@Override
|
|
||||||
public void onDownload(File file) {
|
|
||||||
super.onDownload(file);
|
|
||||||
files.add(file);
|
|
||||||
send(imgs.size(), text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception e) {
|
|
||||||
super.onError(e);
|
|
||||||
index++;
|
|
||||||
send(imgs.size(), text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void send(int size, String text) {
|
|
||||||
if ((files.size() + index) == size) {
|
|
||||||
String str = getInstance().sendMessage(files, text);
|
|
||||||
Log.i("str = " + str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendVersion() {
|
|
||||||
String msg = "软件版本:" + BilibiliApplication.version;
|
|
||||||
QQBotManager.getInstance().sendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package com.yutou.bilibili.Services;
|
|
||||||
|
|
||||||
public interface ISystemConfigService {
|
|
||||||
String getConfig(String key);
|
|
||||||
void setConfig(String key,String value);
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.yutou.bilibili.Services;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.mybatis.model.UBiliUp;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUser;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface IUserService {
|
|
||||||
boolean login(String uname,String password);
|
|
||||||
boolean reg(UUser user);
|
|
||||||
boolean addUp(UBiliUp up);
|
|
||||||
boolean removeUp(UUser user,UBiliUp up);
|
|
||||||
boolean update(UUser user);
|
|
||||||
UUser getUser(String uname);
|
|
||||||
UUser getUserToUid(Integer uid);
|
|
||||||
UUser getUserToToken(String token);
|
|
||||||
List<UBiliUp> getUserUp(int uid);
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.yutou.bilibili.Services.impl;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
|
||||||
import com.yutou.bilibili.mybatis.dao.SConfigDao;
|
|
||||||
import com.yutou.bilibili.mybatis.model.SConfig;
|
|
||||||
import com.yutou.bilibili.mybatis.model.SConfigExample;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service("SystemConfigService")
|
|
||||||
public class SystemConfigImpl implements ISystemConfigService {
|
|
||||||
@Resource
|
|
||||||
SConfigDao configDao;
|
|
||||||
@Override
|
|
||||||
public String getConfig(String key) {
|
|
||||||
SConfigExample example=new SConfigExample();
|
|
||||||
example.createCriteria().andConfigkeyEqualTo(key);
|
|
||||||
List<SConfig> list=configDao.selectByExample(example);
|
|
||||||
if(list.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}else{
|
|
||||||
return list.get(0).getConfigvalue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setConfig(String key, String value) {
|
|
||||||
SConfig config=new SConfig();
|
|
||||||
if(getConfig(key)!=null){
|
|
||||||
SConfigExample example=new SConfigExample();
|
|
||||||
example.createCriteria().andConfigkeyEqualTo(key);
|
|
||||||
config=configDao.selectByExample(example).get(0);
|
|
||||||
config.setConfigvalue(value);
|
|
||||||
configDao.updateByPrimaryKey(config);
|
|
||||||
}else {
|
|
||||||
config.setConfigkey(key);
|
|
||||||
config.setConfigvalue(value);
|
|
||||||
configDao.insert(config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
package com.yutou.bilibili.Services.impl;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.Services.IUserService;
|
|
||||||
import com.yutou.bilibili.Tools.AppTools;
|
|
||||||
import com.yutou.bilibili.mybatis.dao.UBiliUpDao;
|
|
||||||
import com.yutou.bilibili.mybatis.dao.UUserDao;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UBiliUp;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UBiliUpExample;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUser;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUserExample;
|
|
||||||
import org.apache.tomcat.util.security.MD5Encoder;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service("UserService")
|
|
||||||
public class UserServiceImpl implements IUserService {
|
|
||||||
@Resource
|
|
||||||
UUserDao userDao;
|
|
||||||
@Resource
|
|
||||||
UBiliUpDao upDao;
|
|
||||||
@Override
|
|
||||||
public boolean login(String uname, String password) {
|
|
||||||
UUserExample example=new UUserExample();
|
|
||||||
String _password=AppTools.getMD5 (password);
|
|
||||||
example.createCriteria().andUserEqualTo(uname).andPasswordEqualTo(_password);
|
|
||||||
return !userDao.selectByExample(example).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean reg(UUser user) {
|
|
||||||
if(checkUser(user.getUser())){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
user.setPassword(AppTools.getMD5 (user.getPassword()));
|
|
||||||
return userDao.insert(user)>0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addUp(UBiliUp up) {
|
|
||||||
if(checkUP(up.getUid(),up.getRoomid())){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return upDao.insert(up)>0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeUp(UUser user, UBiliUp up) {
|
|
||||||
if(checkUP(up.getUid(),up.getRoomid())){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return upDao.deleteByPrimaryKey(up.getId())>0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean update(UUser user) {
|
|
||||||
return userDao.updateByPrimaryKey(user)>0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUser getUser(String uname) {
|
|
||||||
UUserExample example=new UUserExample();
|
|
||||||
example.createCriteria().andUserEqualTo(uname);
|
|
||||||
List<UUser> list=userDao.selectByExample(example);
|
|
||||||
if(list.isEmpty()){
|
|
||||||
return null;
|
|
||||||
}else{
|
|
||||||
return list.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUser getUserToUid(Integer uid) {
|
|
||||||
return userDao.selectByPrimaryKey(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<UBiliUp> getUserUp(int uid) {
|
|
||||||
UBiliUpExample example=new UBiliUpExample();
|
|
||||||
example.createCriteria().andUidEqualTo(uid);
|
|
||||||
return upDao.selectByExample(example);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUser getUserToToken(String token) {
|
|
||||||
if(StringUtils.isEmpty(token)){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
UUserExample example=new UUserExample();
|
|
||||||
example.createCriteria().andLogintokenEqualTo(token);
|
|
||||||
List<UUser> list=userDao.selectByExample(example);
|
|
||||||
if(list.isEmpty()){
|
|
||||||
return null;
|
|
||||||
}else{
|
|
||||||
return list.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkUser(String uname){
|
|
||||||
UUserExample example=new UUserExample();
|
|
||||||
example.createCriteria().andUserEqualTo(uname);
|
|
||||||
return !userDao.selectByExample(example).isEmpty();
|
|
||||||
}
|
|
||||||
public boolean checkUP(int uid,int roomId){
|
|
||||||
UBiliUpExample example=new UBiliUpExample();
|
|
||||||
example.createCriteria().andUidEqualTo(uid).andRoomidEqualTo(roomId);
|
|
||||||
return !upDao.selectByExample(example).isEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +1,20 @@
|
|||||||
package com.yutou.bilibili.Test;
|
package com.yutou.bilibili.Test;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.yutou.bilibili.Tools.AESTools;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.Live;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.LiveT;
|
|
||||||
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class TestController {
|
public class TestController {
|
||||||
|
@RequestMapping("/test")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequestMapping("/add.do")
|
public String test() {
|
||||||
public String test(int a) {
|
return "f";
|
||||||
|
|
||||||
return "ok";
|
|
||||||
}
|
}
|
||||||
|
@RequestMapping("/test2")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequestMapping("/get.do")
|
public String test2() {
|
||||||
public JSONObject get(){
|
return AESTools.encrypt("f");
|
||||||
JSONObject json=new JSONObject();
|
|
||||||
JSONArray array=new JSONArray();
|
|
||||||
json.put("size", Live.lives.size());
|
|
||||||
for (Live live :Live.lives.values()) {
|
|
||||||
JSONObject item=new JSONObject();
|
|
||||||
item.put("info", JSON.toJSON(live.getInfo()));
|
|
||||||
item.put("data",JSON.toJSON(live.geData()));
|
|
||||||
item.put("isLive", live.geData().getLive()==1);
|
|
||||||
array.add(item);
|
|
||||||
}
|
|
||||||
json.put("array",array);
|
|
||||||
json.put("saveVideo",JSONArray.toJSON(SaveLive.getInstance().getLiveList()));
|
|
||||||
return json;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
src/main/java/com/yutou/bilibili/Tools/AESTools.java
Normal file
52
src/main/java/com/yutou/bilibili/Tools/AESTools.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class AESTools {
|
||||||
|
private static final String key="fJjSoOM7tDIQN0Ne";
|
||||||
|
private static final String model="AES/ECB/PKCS5Padding";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
* @param value 原文
|
||||||
|
* @return 密文
|
||||||
|
*/
|
||||||
|
public static String encrypt(String value){
|
||||||
|
try {
|
||||||
|
KeyGenerator generator=KeyGenerator.getInstance("AES");
|
||||||
|
generator.init(128);
|
||||||
|
Cipher cipher=Cipher.getInstance(model);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(key.getBytes(),"AES"));
|
||||||
|
byte[] bytes=cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return new String(Base64.getEncoder().encode(bytes));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
* @param value 密文
|
||||||
|
* @return 原文
|
||||||
|
*/
|
||||||
|
public static String decrypt(String value){
|
||||||
|
try {
|
||||||
|
KeyGenerator generator=KeyGenerator.getInstance("AES");
|
||||||
|
generator.init(128);
|
||||||
|
Cipher cipher=Cipher.getInstance(model);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE,new SecretKeySpec(key.getBytes(),"AES"));
|
||||||
|
byte[] encodeBytes=Base64.getDecoder().decode(value);
|
||||||
|
byte[] bytes=cipher.doFinal(encodeBytes);
|
||||||
|
return new String(bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.yutou.bilibili.Services.IUserService;
|
|
||||||
import com.yutou.bilibili.mybatis.dao.PermissionDao;
|
|
||||||
import com.yutou.bilibili.mybatis.model.Permission;
|
|
||||||
import com.yutou.bilibili.mybatis.model.PermissionExample;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUser;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.*;
|
|
||||||
import javax.servlet.annotation.WebFilter;
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@WebFilter
|
|
||||||
public class APIFilter implements Filter {
|
|
||||||
@Resource
|
|
||||||
IUserService service;
|
|
||||||
@Resource
|
|
||||||
PermissionDao permissionDao;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
|
||||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
|
||||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
|
||||||
String token = request.getParameter("token");
|
|
||||||
if (StringUtils.isEmpty(token)) {
|
|
||||||
Cookie cookie = AppTools.getCookie(request, "login");
|
|
||||||
if (cookie != null) {
|
|
||||||
token = cookie.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String tmp = request.getRequestURI();
|
|
||||||
if (tmp.contains("/user/login.do")
|
|
||||||
|| tmp.contains("/user/reg.do")
|
|
||||||
|| tmp.contains("/user/logout.do")
|
|
||||||
|| tmp.contains("/user/get/test.do")
|
|
||||||
|| tmp.contains("/system/public/reg.do")
|
|
||||||
|| tmp.contains("/favicon.ico")
|
|
||||||
) {
|
|
||||||
filterChain.doFilter(servletRequest, servletResponse);
|
|
||||||
} else {
|
|
||||||
if (StringUtils.isEmpty(token)) {
|
|
||||||
response.sendRedirect("/");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UUser user = service.getUserToUid(Integer.parseInt(RedisTools.get(token)));
|
|
||||||
if (user == null) {
|
|
||||||
response.sendRedirect("/");
|
|
||||||
} else {
|
|
||||||
String url = null;
|
|
||||||
try {
|
|
||||||
url = tmp.split(tmp.split("/")[tmp.split("/").length - 1])[0];
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("无权限请求:" + tmp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JSONArray powers = JSONArray.parseArray(user.getPower());
|
|
||||||
if (powers.toJavaList(Integer.class).contains(-1)) {
|
|
||||||
filterChain.doFilter(servletRequest, servletResponse);
|
|
||||||
} else {
|
|
||||||
PermissionExample pExample = new PermissionExample();
|
|
||||||
pExample.createCriteria().andUrlEqualTo(url);
|
|
||||||
List<Permission> permissions = permissionDao.selectByExample(pExample);
|
|
||||||
if (permissions != null && permissions.size() > 0) {
|
|
||||||
if (powers.toJavaList(Integer.class).contains(permissions.get(0).getId())) {
|
|
||||||
filterChain.doFilter(servletRequest, servletResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,19 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
|
import com.yutou.bilibili.services.SystemService;
|
||||||
|
import com.yutou.common.utils.Log;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.context.event.ContextClosedEvent;
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class ApplicationClose implements ApplicationListener<ContextClosedEvent> {
|
public class ApplicationClose implements ApplicationListener<ContextClosedEvent> {
|
||||||
|
@Resource
|
||||||
|
SystemService systemConfigService;
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
|
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
|
||||||
Log.i("服务结束");
|
Log.i("服务结束");
|
||||||
|
systemConfigService.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,13 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.AppData;
|
import com.yutou.bilibili.services.SystemService;
|
||||||
import com.yutou.bilibili.BiliBili.Datas.LiveData;
|
import jakarta.annotation.Resource;
|
||||||
import com.yutou.bilibili.BiliBili.Live;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
import com.yutou.bilibili.BiliBili.Services.IBiliBiliLiveService;
|
|
||||||
import com.yutou.bilibili.Services.ISystemConfigService;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
|
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import java.util.logging.Level;
|
||||||
import java.io.File;
|
import java.util.logging.Logger;
|
||||||
import java.text.ParsePosition;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 服务启动后执行
|
* 服务启动后执行
|
||||||
@@ -28,117 +15,13 @@ import java.util.TimerTask;
|
|||||||
@Component
|
@Component
|
||||||
public class ApplicationInit implements ApplicationRunner {
|
public class ApplicationInit implements ApplicationRunner {
|
||||||
@Resource
|
@Resource
|
||||||
IBiliBiliLiveService service;
|
SystemService systemConfigService;
|
||||||
@Resource
|
|
||||||
ISystemConfigService configService;
|
|
||||||
private Timer timer;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
LiveUtils.LiveGiftConfig.getInstance();
|
Logger logger = Logger.getLogger("ApplicationInit");
|
||||||
AppData.FFMPEG = configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG);
|
logger.log(Level.INFO, "服务启动后执行");
|
||||||
AppData.LIVE_SAVE_FFMPEG = configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL) != null && configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL).equals("ffmpeg");
|
systemConfigService.start();
|
||||||
startTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startTimer() {
|
|
||||||
if (timer == null) {
|
|
||||||
timer = new Timer();
|
|
||||||
timer.schedule(new TimerTask() {
|
|
||||||
String oldTime = "";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Date date = new Date();
|
|
||||||
String time = new SimpleDateFormat("HH:mm").format(date);
|
|
||||||
if (time.equals(oldTime)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
checkLive();
|
|
||||||
oldTime = time;
|
|
||||||
switch (time) {
|
|
||||||
case "00:00":
|
|
||||||
for (Live live : Live.lives.values()) {
|
|
||||||
live.clearInfo();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "01:00":
|
|
||||||
case "02:00":
|
|
||||||
case "03:00":
|
|
||||||
case "04:00":
|
|
||||||
case "05:00":
|
|
||||||
case "06:00":
|
|
||||||
case "07:00":
|
|
||||||
case "08:00":
|
|
||||||
case "09:00":
|
|
||||||
case "10:00":
|
|
||||||
case "11:00":
|
|
||||||
case "12:00":
|
|
||||||
case "13:00":
|
|
||||||
case "14:00":
|
|
||||||
case "15:00":
|
|
||||||
case "16:00":
|
|
||||||
case "17:00":
|
|
||||||
case "18:00":
|
|
||||||
case "19:00":
|
|
||||||
case "20:00":
|
|
||||||
case "21:00":
|
|
||||||
case "22:00":
|
|
||||||
case "23:00":
|
|
||||||
case "23:59":
|
|
||||||
saveData(time);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkLive() {
|
|
||||||
List<BilibiliUpInfo> list = service.getUpInfo();
|
|
||||||
LiveUtils.reloadLiveState(list);
|
|
||||||
for (BilibiliUpInfo info : list) {
|
|
||||||
if (info.getOfflinelistening() == 1) {
|
|
||||||
if (info.getEnable() == 1 ) {
|
|
||||||
Live live = LiveUtils.liveContains(info);
|
|
||||||
if (live == null) {
|
|
||||||
live = new Live();
|
|
||||||
live.add(info.getRoomid(), !StringUtils.isEmpty(AppTools.readFile(new File("cookies.json"))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 0, 2 * 60 * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveData(String time) {
|
|
||||||
Date date = new Date();
|
|
||||||
String toDay = AppTools.getToDayTime() + " 00:00:00";
|
|
||||||
String nowTime = AppTools.getToDayTime() + " " + time + ":00";
|
|
||||||
for (BilibiliUpInfo info : service.getUpInfo()) {
|
|
||||||
Date startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(toDay, new ParsePosition(0));
|
|
||||||
Date endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(nowTime, new ParsePosition(0));
|
|
||||||
int userCount = service.queryLiveData(info.getRoomid(), startTime, endTime, new String[]{LiveData.INTERACT_WORD}).size();
|
|
||||||
int vipCount = service.queryLiveData(info.getRoomid(), startTime, endTime, new String[]{LiveData.ENTRY_EFFECT}).size();
|
|
||||||
int giftCount = service.queryLiveData(info.getRoomid(), startTime, endTime, new String[]{
|
|
||||||
LiveData.SEND_GIFT,
|
|
||||||
LiveData.COMBO_SEND,
|
|
||||||
LiveData.GUARD_BUY,
|
|
||||||
LiveData.SUPER_CHAT_MESSAGE}).size();
|
|
||||||
Live live = LiveUtils.liveContains(info);
|
|
||||||
int popularCount = 0;
|
|
||||||
if (live != null) {
|
|
||||||
popularCount = live.getInfo().getPopular();
|
|
||||||
}
|
|
||||||
BilibiliLiveInfo liveInfo = new BilibiliLiveInfo();
|
|
||||||
liveInfo.setRoomid(info.getRoomid());
|
|
||||||
liveInfo.setGiftuser(giftCount);
|
|
||||||
liveInfo.setUserindex(userCount);
|
|
||||||
liveInfo.setVipuserindex(vipCount);
|
|
||||||
liveInfo.setPopular(popularCount);
|
|
||||||
liveInfo.setSubtime(date);
|
|
||||||
service.addLiveInfo(liveInfo);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.DanmuData;
|
import com.yutou.bilibili.datas.DanmuData;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
@@ -17,7 +17,7 @@ public class AssTools {
|
|||||||
private final Date startTime;
|
private final Date startTime;
|
||||||
private int y = 0;
|
private int y = 0;
|
||||||
private List<String> filters = new ArrayList<>();
|
private List<String> filters = new ArrayList<>();
|
||||||
private String alpha="80";
|
private String alpha="100";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 弹幕转换ass
|
* 弹幕转换ass
|
||||||
@@ -140,7 +140,7 @@ public class AssTools {
|
|||||||
y,
|
y,
|
||||||
x2,
|
x2,
|
||||||
y,
|
y,
|
||||||
danmuData.getFontColorHex(),
|
danmuData.getFontColor(),
|
||||||
alpha,
|
alpha,
|
||||||
danmuData.getDanmu()
|
danmuData.getDanmu()
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
|
||||||
|
|
||||||
public class Config {
|
|
||||||
public static final String USER_REG="userReg";
|
|
||||||
public static final String BILI_LIVE_FLAG="biliLive";
|
|
||||||
public static final String SYSTEM_VIDEO_FFMPEG="ffmpeg_path";
|
|
||||||
public static final String SYSTEM_VIDEO_SAVE_MODEL="save_live_model";
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.BiliBili.Datas.DanmuData;
|
|
||||||
import com.yutou.bilibili.sqlite.BiliBiliLiveDatabasesManager;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
|
||||||
import java.nio.file.attribute.FileTime;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class DanmuTools {
|
|
||||||
public static File danmuToAss(File live, File danmu, boolean useFileNameData, String... filterDanmu) {
|
|
||||||
BiliBiliLiveDatabasesManager manager = new BiliBiliLiveDatabasesManager();
|
|
||||||
try {
|
|
||||||
FileTime creationTime = Files.readAttributes(Paths.get(live.getAbsolutePath()), BasicFileAttributes.class).creationTime();
|
|
||||||
FileTime lastModifiedTime = Files.readAttributes(Paths.get(live.getAbsolutePath()), BasicFileAttributes.class).lastModifiedTime();
|
|
||||||
Date startTime;
|
|
||||||
if (useFileNameData) {
|
|
||||||
startTime = getLiveDate(live.getName());
|
|
||||||
} else {
|
|
||||||
startTime = new Date(creationTime.toMillis());
|
|
||||||
}
|
|
||||||
manager.init(danmu);
|
|
||||||
List<DanmuData> danmuData = manager.queryDanmu(startTime, new Date(lastModifiedTime.toMillis()));
|
|
||||||
AssTools assTools = new AssTools(live.getName(), startTime);
|
|
||||||
assTools.addFilter(filterDanmu);
|
|
||||||
assTools.setAlpha(128);
|
|
||||||
for (DanmuData danmuDatum : danmuData) {
|
|
||||||
assTools.addDanmu(danmuDatum);
|
|
||||||
}
|
|
||||||
assTools.saveDanmu(live.getAbsolutePath().replace(live.getName().substring(live.getName().lastIndexOf(".")), ".ass"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
manager.close();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Date getLiveDate(String fileName) {
|
|
||||||
Pattern pattern = Pattern.compile("(\\[.*\\]).");
|
|
||||||
Matcher matcher = pattern.matcher(fileName);
|
|
||||||
if (matcher.find()) {
|
|
||||||
String str = matcher.group(1);
|
|
||||||
try {
|
|
||||||
return new SimpleDateFormat("[yyyy-MM-dd HHmmss]").parse(str);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
File live = new File("Z:\\download\\演唱会or录播\\2022年2月11日Liyuu_1st演唱会\\[2022-02-11 163454]5265.mp4");
|
|
||||||
File danmu = new File("Z:\\download\\演唱会or录播\\2022年2月11日Liyuu_1st演唱会\\[2022-02-11]5265.db");
|
|
||||||
danmuToAss(live, danmu,true, "老板大气!点点红包抽礼物!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
22
src/main/java/com/yutou/bilibili/Tools/DateFormatUtils.java
Normal file
22
src/main/java/com/yutou/bilibili/Tools/DateFormatUtils.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class DateFormatUtils {
|
||||||
|
public static String format(Date date,String format){
|
||||||
|
return new SimpleDateFormat(format).format(date);
|
||||||
|
}
|
||||||
|
public static String format(long time,String format){
|
||||||
|
return new SimpleDateFormat(format).format(new Date(time));
|
||||||
|
}
|
||||||
|
public static String format(long time){
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(time));
|
||||||
|
}
|
||||||
|
public static String format(Date date){
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date);
|
||||||
|
}
|
||||||
|
public static String format(){
|
||||||
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
|
||||||
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliLiveDataDao;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.dao.BilibiliLiveInfoDao;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveData;
|
|
||||||
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
|
|
||||||
import org.apache.poi.ss.usermodel.*;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static com.yutou.bilibili.BiliBili.Datas.LiveData.*;
|
|
||||||
|
|
||||||
public class ExcelUtils implements ApplicationContextAware {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
BilibiliLiveDataDao dataDao;
|
|
||||||
@Resource
|
|
||||||
BilibiliLiveInfoDao infoDao;
|
|
||||||
|
|
||||||
public static File getInstance(int roomId, Date startTime, Date endTime,String fileName) {
|
|
||||||
ExcelUtils utils = new ExcelUtils();
|
|
||||||
long timer=System.currentTimeMillis();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("开始注入bean");
|
|
||||||
utils.dataDao = getBean(BilibiliLiveDataDao.class);
|
|
||||||
utils.infoDao = getBean(BilibiliLiveInfoDao.class);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("注入完毕:"+(System.currentTimeMillis()-timer));
|
|
||||||
return utils.initTable(roomId, startTime, endTime,fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExcelUtils() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private File initTable(int roomId, Date startTime, Date endTime,String fileName) {
|
|
||||||
long timer=System.currentTimeMillis();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("进入统计:"+timer);
|
|
||||||
Workbook workbook = new XSSFWorkbook();
|
|
||||||
Sheet liveData = workbook.createSheet("直播数据");
|
|
||||||
Sheet liveInfo = workbook.createSheet("小时统计");
|
|
||||||
Row dataRow = liveData.createRow(0);
|
|
||||||
Row infoRow = liveInfo.createRow(0);
|
|
||||||
createCell(dataRow.createCell(0), "id");
|
|
||||||
createCell(dataRow.createCell(1), "uid");
|
|
||||||
createCell(dataRow.createCell(2), "roomId");
|
|
||||||
createCell(dataRow.createCell(3), "类型");
|
|
||||||
createCell(dataRow.createCell(4), "内容");
|
|
||||||
createCell(dataRow.createCell(5), "礼物id");
|
|
||||||
createCell(dataRow.createCell(6), "礼物名称");
|
|
||||||
createCell(dataRow.createCell(7), "礼物数量");
|
|
||||||
createCell(dataRow.createCell(8), "金瓜子");
|
|
||||||
createCell(dataRow.createCell(9), "时间");
|
|
||||||
|
|
||||||
createCell(infoRow.createCell(0), "id");
|
|
||||||
createCell(infoRow.createCell(1), "房间号");
|
|
||||||
createCell(infoRow.createCell(2), "人气");
|
|
||||||
createCell(infoRow.createCell(3), "普通用户入场数量");
|
|
||||||
createCell(infoRow.createCell(4), "舰长入场数量");
|
|
||||||
createCell(infoRow.createCell(5), "送礼人数");
|
|
||||||
createCell(infoRow.createCell(6), "记录时间");
|
|
||||||
|
|
||||||
com.yutou.bilibili.Tools.Log.i("表头插入完毕:"+(System.currentTimeMillis()-timer));
|
|
||||||
List<BilibiliLiveData> dataList = dataDao.queryLiveData(roomId, startTime, endTime, new String[]{
|
|
||||||
INTERACT_WORD,
|
|
||||||
ENTRY_EFFECT,
|
|
||||||
DANMU_MSG,
|
|
||||||
SEND_GIFT,
|
|
||||||
COMBO_SEND,
|
|
||||||
SUPER_CHAT_MESSAGE,
|
|
||||||
NOTICE_MSG,
|
|
||||||
GUARD_BUY,
|
|
||||||
UNKNOWN_MESSAGE
|
|
||||||
});
|
|
||||||
List<BilibiliLiveInfo> infoList = infoDao.queryTimeOfRoomid(roomId, startTime, endTime);
|
|
||||||
int index = 1;
|
|
||||||
for (BilibiliLiveData data : dataList) {
|
|
||||||
dataRow = liveData.createRow(index++);
|
|
||||||
createCell(dataRow.createCell(0), data.getId());
|
|
||||||
createCell(dataRow.createCell(1), data.getUid());
|
|
||||||
createCell(dataRow.createCell(2), data.getRoomid());
|
|
||||||
createCell(dataRow.createCell(3), data.getType());
|
|
||||||
createCell(dataRow.createCell(4), data.getMsg());
|
|
||||||
createCell(dataRow.createCell(5), data.getGiftid());
|
|
||||||
createCell(dataRow.createCell(6), data.getGiftname());
|
|
||||||
createCell(dataRow.createCell(7), data.getGiftindex());
|
|
||||||
createCell(dataRow.createCell(8), data.getPrice());
|
|
||||||
createCell(dataRow.createCell(9), AppTools.getToDayTimeToString(data.getSubtime()));
|
|
||||||
}
|
|
||||||
index = 1;
|
|
||||||
for (BilibiliLiveInfo info : infoList) {
|
|
||||||
infoRow = liveInfo.createRow(index++);
|
|
||||||
createCell(infoRow.createCell(0), info.getId());
|
|
||||||
createCell(infoRow.createCell(1), info.getRoomid());
|
|
||||||
createCell(infoRow.createCell(2), info.getPopular());
|
|
||||||
createCell(infoRow.createCell(3), info.getUserindex());
|
|
||||||
createCell(infoRow.createCell(4), info.getVipuserindex());
|
|
||||||
createCell(infoRow.createCell(5), info.getGiftuser());
|
|
||||||
createCell(infoRow.createCell(6), AppTools.getToDayTimeToString(info.getSubtime()));
|
|
||||||
}
|
|
||||||
com.yutou.bilibili.Tools.Log.i("数据填充完毕:"+(System.currentTimeMillis()-timer));
|
|
||||||
try {
|
|
||||||
if(!new File("excel").exists()){
|
|
||||||
new File("excel").mkdirs();
|
|
||||||
}
|
|
||||||
File file = new File("excel"+File.separator+fileName+".tmp");
|
|
||||||
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
|
||||||
workbook.write(fileOutputStream);
|
|
||||||
workbook.close();
|
|
||||||
com.yutou.bilibili.Tools.Log.i("文件写入完毕:"+(System.currentTimeMillis()-timer));
|
|
||||||
file.renameTo(new File("excel"+File.separator+fileName));
|
|
||||||
return file;
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createCell(Cell cell, Object data) {
|
|
||||||
if (data == null)
|
|
||||||
data = 0;
|
|
||||||
if (data instanceof String) {
|
|
||||||
cell.setCellType(CellType.STRING);
|
|
||||||
cell.setCellValue((String) data);
|
|
||||||
} else {
|
|
||||||
cell.setCellType(CellType.NUMERIC);
|
|
||||||
|
|
||||||
cell.setCellValue((int) data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
if (ExcelUtils.applicationContext == null) {
|
|
||||||
ExcelUtils.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getBean(Class<T> clazz) {
|
|
||||||
return applicationContext.getBean(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
|
import com.yutou.common.utils.AppTools;
|
||||||
|
import com.yutou.common.utils.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -38,7 +41,7 @@ public class FFmpegUtils {
|
|||||||
ffmpeg,
|
ffmpeg,
|
||||||
file.getAbsolutePath(),
|
file.getAbsolutePath(),
|
||||||
out.getAbsolutePath() + File.separator + file.getName());
|
out.getAbsolutePath() + File.separator + file.getName());
|
||||||
com.yutou.bilibili.Tools.Log.i(exec);
|
Log.i(exec);
|
||||||
Process process= AppTools.exec(exec);
|
Process process= AppTools.exec(exec);
|
||||||
InputStream inputStream = process.getErrorStream();
|
InputStream inputStream = process.getErrorStream();
|
||||||
byte[] bytes = new byte[1024];
|
byte[] bytes = new byte[1024];
|
||||||
@@ -49,7 +52,7 @@ public class FFmpegUtils {
|
|||||||
file.delete();
|
file.delete();
|
||||||
new File(out.getAbsolutePath()+File.separator+file.getName()).delete();
|
new File(out.getAbsolutePath()+File.separator+file.getName()).delete();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
}
|
}
|
||||||
nowFFmpegList.remove(file);
|
nowFFmpegList.remove(file);
|
||||||
}
|
}
|
||||||
@@ -61,13 +64,13 @@ public class FFmpegUtils {
|
|||||||
int i = -1;
|
int i = -1;
|
||||||
while (i != 1) {
|
while (i != 1) {
|
||||||
i = add("D:\\ffmpeg-4.3.1-2020-11-19-full_build\\bin\\ffmpeg.exe", file.getAbsoluteFile(), new File("ffmpeg_out"));
|
i = add("D:\\ffmpeg-4.3.1-2020-11-19-full_build\\bin\\ffmpeg.exe", file.getAbsoluteFile(), new File("ffmpeg_out"));
|
||||||
com.yutou.bilibili.Tools.Log.i(i);
|
Log.i(i);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(300);
|
Thread.sleep(300);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
Log.e(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
com.yutou.bilibili.Tools.Log.i("转码完成");
|
Log.i("转码完成");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/main/java/com/yutou/bilibili/Tools/FileServerUtils.java
Normal file
18
src/main/java/com/yutou/bilibili/Tools/FileServerUtils.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package com.yutou.bilibili.Tools;
|
||||||
|
|
||||||
|
import com.yutou.common.utils.Base64Tools;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class FileServerUtils {
|
||||||
|
public static String toUrl(String file) {
|
||||||
|
return "/file/" + URLEncoder.encode(Base64Tools.encode(file), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File toFile(String base64) {
|
||||||
|
return new File(URLDecoder.decode(Base64Tools.decode(base64), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,261 +0,0 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.interfaces.DownloadInterface;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class HttpTools {
|
|
||||||
private static final int HttpRequestIndex = 3;
|
|
||||||
|
|
||||||
public static String get(String url) {
|
|
||||||
return https_get(url, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String post(final String url, final byte[] body) {
|
|
||||||
return http_post(url, body, 0, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File syncDownload(final String url, final String saveName) {
|
|
||||||
return new HttpTools().http_syncDownload(url, saveName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String https_get(String url, Map<String, String> header) {
|
|
||||||
try {
|
|
||||||
URLConnection connection;
|
|
||||||
connection = new URL(url).openConnection();
|
|
||||||
connection.setConnectTimeout(60*1000);
|
|
||||||
connection.setReadTimeout(60*1000);
|
|
||||||
connection.setRequestProperty("User-Agent", getExtUa());
|
|
||||||
if (header != null) {
|
|
||||||
for (String key : header.keySet()) {
|
|
||||||
connection.addRequestProperty(key, header.get(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connection.connect();
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
StringBuilder str = new StringBuilder();
|
|
||||||
String tmp;
|
|
||||||
while ((tmp = reader.readLine()) != null) {
|
|
||||||
str.append(tmp).append("\n");
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
return str.toString();
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("error url = " + url);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String http_post(String url, byte[] body, int index, Map<String, String> headers) {
|
|
||||||
String tmp;
|
|
||||||
StringBuilder str = new StringBuilder();
|
|
||||||
try {
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
if (headers != null) {
|
|
||||||
for (String key : headers.keySet()) {
|
|
||||||
connection.addRequestProperty(key, headers.get(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
connection.setDoInput(true);
|
|
||||||
connection.addRequestProperty("User-Agent", getExtUa());
|
|
||||||
connection.setConnectTimeout(5 * 1000);
|
|
||||||
connection.setReadTimeout(10 * 1000);
|
|
||||||
//connection.addRequestProperty("Connection", "keep-alive");
|
|
||||||
//connection.addRequestProperty("User-Agent", getExtUa());
|
|
||||||
connection.addRequestProperty("content-type", "application/json");
|
|
||||||
//connection.addRequestProperty("charset", "UTF-8");
|
|
||||||
OutputStream outputStream = connection.getOutputStream();
|
|
||||||
//System.out.println(new String(body));
|
|
||||||
outputStream.write(body);
|
|
||||||
outputStream.flush();
|
|
||||||
outputStream.close();
|
|
||||||
connection.connect();
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
||||||
while ((tmp = reader.readLine()) != null) {
|
|
||||||
str.append(tmp);
|
|
||||||
}
|
|
||||||
String finalStr = str.toString();
|
|
||||||
|
|
||||||
connection.disconnect();
|
|
||||||
reader.close();
|
|
||||||
return finalStr;
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (index < HttpRequestIndex) {
|
|
||||||
return http_post(url, body, index + 1, headers);
|
|
||||||
} else {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getExtUa() {
|
|
||||||
return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getKuKuUA() {
|
|
||||||
return "/KUKU_APP(Android/#/cn.kuku.sdk/ttsdk17228/29401/A-2.9.4.01.KUSDK/868139039134314/fcddf839c8c135fa/F4:60:E2:AB:25:1A/460019406520644/+8618569400341/#/9/Redmi 6 Pro/xiaomi/1736/76fda4d6-cd6b-485f-987b-8d347b007f24/#/KUKU/Native/92972ea9651fbd2e)";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String toUrlParams(JSONObject json) {
|
|
||||||
StringBuilder string = new StringBuilder();
|
|
||||||
Set<String> keys = json.keySet();
|
|
||||||
for (String key : keys) {
|
|
||||||
try {
|
|
||||||
string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key),"utf-8"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
try {
|
|
||||||
string.append("&").append(URLEncoder.encode(key, "utf-8")).append("=");
|
|
||||||
// string += "&" + key + "=";
|
|
||||||
} catch (Exception e1) {
|
|
||||||
string.append("&").append(key).append("=");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string = new StringBuilder(string.substring(1, string.length()).replaceAll(" ", ""));
|
|
||||||
return string.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("pid", "102");
|
|
||||||
json.put("gid", "100584");
|
|
||||||
json.put("gameKey", "0gha58u1c9FjZkeAsEmYIzTvp");
|
|
||||||
json.put("access_token", "659c-S1gV0DwMXdYjPDlSrSLNYOvA8qUoCSvmdFEHvZugKgNX4Z2BCwF18A7W2gRdG7WiWfKsbZgF6YssZHhaozksI9RBn2QQFTXzmAHtbMd4ginEEtwdKmPCM4JbJGg1ollqoNE0PcGENpa4F3e7EdSOa_JFyE6XyUQN1iurJU3F8MZfLlTIcTR9USYoHX15vsAkCht_0mrapZblkeY1_8HFrmK8rlenbZLxccy7PrMz5eZ9uPPDJL5OYiEahyrtLENB8SVmlGofJfQw8wUjN8_XVZSfLMujdwz24");
|
|
||||||
String url = "http://192.168.1.156:9020/Faxing/reg?" +
|
|
||||||
"&tpyeCode=dimai" +
|
|
||||||
"®ParamJson=" + json.toJSONString();
|
|
||||||
/* ExecutorService service= Executors.newCachedThreadPool();
|
|
||||||
for (int i = 0; i < 3000; i++) {
|
|
||||||
service.submit(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
get(url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String donwloadPath = "tmp" + File.separator;
|
|
||||||
|
|
||||||
public synchronized static void download(final String url, final String saveName, final DownloadInterface downloadInterface) {
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
File jar = null;
|
|
||||||
try {
|
|
||||||
File savePath = new File(donwloadPath);
|
|
||||||
if (!savePath.exists()) {
|
|
||||||
savePath.mkdirs();
|
|
||||||
}
|
|
||||||
Log.i("DOWNLOAD", "下载文件:" + url + " 保存文件:" + saveName);
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
|
||||||
connection.addRequestProperty("User-Agent", getExtUa());
|
|
||||||
// Log.i(TAG,"获取到网络请求:"+connection.getResponseCode());
|
|
||||||
|
|
||||||
|
|
||||||
InputStream inputStream = connection.getInputStream();
|
|
||||||
jar = new File(donwloadPath + saveName + "_tmp.tmp");
|
|
||||||
jar.createNewFile();
|
|
||||||
Log.i("DOWNLOAD", "临时保存文件:" + jar.getAbsolutePath());
|
|
||||||
OutputStream outputStream = new FileOutputStream(jar);
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
double size = connection.getContentLength();
|
|
||||||
double downSize = 0;
|
|
||||||
int len;
|
|
||||||
while ((len = inputStream.read(bytes)) > 0) {
|
|
||||||
outputStream.write(bytes, 0, len);
|
|
||||||
downSize += len;
|
|
||||||
if (downloadInterface != null) {
|
|
||||||
downloadInterface.onDownloading(downSize, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outputStream.close();
|
|
||||||
inputStream.close();
|
|
||||||
File oldJar = new File(donwloadPath + saveName);
|
|
||||||
if (oldJar.exists()) {
|
|
||||||
oldJar.delete();
|
|
||||||
}
|
|
||||||
jar.renameTo(oldJar);
|
|
||||||
Log.i("DOWNLOAD", "实际保存:" + oldJar.getAbsolutePath() + " " + oldJar.getName());
|
|
||||||
if (downloadInterface != null) {
|
|
||||||
downloadInterface.onDownload(oldJar);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
if (jar != null) {
|
|
||||||
jar.delete();
|
|
||||||
}
|
|
||||||
if (downloadInterface != null) {
|
|
||||||
downloadInterface.onError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized File http_syncDownload(final String url, final String saveName) {
|
|
||||||
if (StringUtils.isEmpty(url)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
File jar = null;
|
|
||||||
try {
|
|
||||||
File savePath = new File(donwloadPath);
|
|
||||||
if (!savePath.exists()) {
|
|
||||||
savePath.mkdirs();
|
|
||||||
}
|
|
||||||
Log.i("DOWNLOAD", "下载文件:" + url + " 保存文件:" + saveName);
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
|
||||||
connection.addRequestProperty("User-Agent", getExtUa());
|
|
||||||
// Log.i(TAG,"获取到网络请求:"+connection.getResponseCode());
|
|
||||||
|
|
||||||
|
|
||||||
InputStream inputStream = connection.getInputStream();
|
|
||||||
jar = new File(donwloadPath + saveName + "_tmp.tmp");
|
|
||||||
jar.createNewFile();
|
|
||||||
Log.i("DOWNLOAD", "临时保存文件:" + jar.getAbsolutePath());
|
|
||||||
OutputStream outputStream = new FileOutputStream(jar);
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
double size = connection.getContentLength();
|
|
||||||
double downSize = 0;
|
|
||||||
int len;
|
|
||||||
while ((len = inputStream.read(bytes)) > 0) {
|
|
||||||
outputStream.write(bytes, 0, len);
|
|
||||||
downSize += len;
|
|
||||||
}
|
|
||||||
outputStream.close();
|
|
||||||
inputStream.close();
|
|
||||||
File oldJar = new File(donwloadPath + saveName);
|
|
||||||
if (oldJar.exists()) {
|
|
||||||
oldJar.delete();
|
|
||||||
}
|
|
||||||
connection.disconnect();
|
|
||||||
jar.renameTo(oldJar);
|
|
||||||
Log.i("DOWNLOAD", "实际保存:" + oldJar.getAbsolutePath() + " " + oldJar.getName());
|
|
||||||
return oldJar;
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
if (jar != null) {
|
|
||||||
jar.delete();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.yutou.bilibili.Services.IUserService;
|
|
||||||
import com.yutou.bilibili.mybatis.dao.PermissionDao;
|
|
||||||
import com.yutou.bilibili.mybatis.model.Permission;
|
|
||||||
import com.yutou.bilibili.mybatis.model.PermissionExample;
|
|
||||||
import com.yutou.bilibili.mybatis.model.UUser;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ServiceTools implements ApplicationContextAware {
|
|
||||||
private static ApplicationContext applicationContext = null;
|
|
||||||
@Resource
|
|
||||||
IUserService userService;
|
|
||||||
@Resource
|
|
||||||
PermissionDao permissionDao;
|
|
||||||
|
|
||||||
public static ServiceTools getInstance() {
|
|
||||||
ServiceTools tools=new ServiceTools();
|
|
||||||
tools.userService=getBean(IUserService.class);
|
|
||||||
tools.permissionDao=getBean(PermissionDao.class);
|
|
||||||
return tools;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean auth(HttpServletRequest request, String uname, String path) {
|
|
||||||
UUser user = userService.getUser(uname);
|
|
||||||
String tmp = request.getRequestURI();
|
|
||||||
String url = null;
|
|
||||||
try {
|
|
||||||
url = tmp.split(tmp.split("/")[tmp.split("/").length - 1])[0];
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
com.yutou.bilibili.Tools.Log.i("无权限请求:" + tmp);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
JSONArray powers = JSONArray.parseArray(user.getPower());
|
|
||||||
if (powers.toJavaList(Integer.class).contains(-1)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
PermissionExample pExample = new PermissionExample();
|
|
||||||
pExample.createCriteria().andUrlEqualTo(url);
|
|
||||||
List<Permission> permissions = permissionDao.selectByExample(pExample);
|
|
||||||
if (permissions != null && permissions.size() > 0) {
|
|
||||||
if (powers.toJavaList(Integer.class).contains(permissions.get(0).getId())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
|
||||||
if (ServiceTools.applicationContext == null) {
|
|
||||||
ServiceTools.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getBean(Class<T> clazz) {
|
|
||||||
return applicationContext.getBean(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package com.yutou.bilibili.Tools;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.yutou.bilibili.BiliBili.LiveUtils;
|
|
||||||
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.CookieHandler;
|
|
||||||
import java.net.CookieManager;
|
|
||||||
import java.net.HttpCookie;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TestMain {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
new TestMain();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TestMain() {
|
|
||||||
try {
|
|
||||||
JSONObject cookie = JSONObject.parseObject(LiveUtils.getFile("cookies.json"));
|
|
||||||
JSONObject userHear = new JSONObject();
|
|
||||||
userHear.put("csrf_token",cookie.getString("bili_jct"));
|
|
||||||
userHear.put("csrf",cookie.getString("bili_jct"));
|
|
||||||
userHear.put("visit_id","");
|
|
||||||
HttpURLConnection connection=LiveUtils.getBiliHttpPost("https://api.live.bilibili.com/User/userOnlineHeart",LiveUtils.getCookie());
|
|
||||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
|
||||||
|
|
||||||
OutputStream connectionOutputStream = null;
|
|
||||||
connectionOutputStream = connection.getOutputStream();
|
|
||||||
connectionOutputStream.write(HttpTools.toUrlParams(userHear).getBytes(StandardCharsets.UTF_8));
|
|
||||||
connectionOutputStream.flush();
|
|
||||||
JSONObject hearBeat;
|
|
||||||
hearBeat=LiveUtils.http_post("https://api.live.bilibili.com/User/userOnlineHeart", HttpTools.toUrlParams(userHear));
|
|
||||||
/* BufferedInputStream stream = new BufferedInputStream(connection.getInputStream());
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int len = 0, size;
|
|
||||||
while ((len = stream.read(bytes)) != -1) {
|
|
||||||
outputStream.write(bytes, 0, len);
|
|
||||||
outputStream.flush();
|
|
||||||
}
|
|
||||||
String str = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);*/
|
|
||||||
|
|
||||||
com.yutou.bilibili.Tools.Log.i("["+AppTools.getToDayNowTimeToString()+"]"+hearBeat);
|
|
||||||
} catch (Exception e) {
|
|
||||||
com.yutou.bilibili.Tools.Log.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static int byteArrayToInt(byte[] bytes) {
|
|
||||||
int value=0;
|
|
||||||
for(int i = 0; i < 4; i++) {
|
|
||||||
int shift= (3-i) * 8;
|
|
||||||
value +=(bytes[i] & 0xFF) << shift;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user