新版改版:

模块化各个功能
改为okhttp网络请求
改为sqlite作为存储
预设QQ机器人API
This commit is contained in:
zlzw 2024-06-15 15:53:48 +08:00
parent 6482c919f0
commit b178010f8f
103 changed files with 3519 additions and 3460 deletions

26
biliapi/pom.xml Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yutou</groupId>
<artifactId>bilibili</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>biliapi</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.reactivex.rxjava3</groupId>
<artifactId>rxjava</artifactId>
<version>3.1.8</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,18 @@
package com.yutou.bili.api;
import com.yutou.bili.bean.login.LoginInfoBean;
import com.yutou.bili.bean.login.QRCodeGenerateBean;
import com.yutou.okhttp.HttpBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface LoginApi {
@GET("/x/passport-login/web/qrcode/generate")
Call<HttpBody<QRCodeGenerateBean>> getQRCodeGenerate();
@GET("/x/passport-login/web/qrcode/poll")
Call<HttpBody<LoginInfoBean>> loginQRCode(@Query("qrcode_key") String qrcode_key);
}

View File

@ -0,0 +1,11 @@
package com.yutou.bili.api;
import com.yutou.bili.bean.login.UserInfoBean;
import com.yutou.okhttp.HttpBody;
import retrofit2.Call;
import retrofit2.http.GET;
public interface UserApi {
@GET("/x/web-interface/nav")
Call<HttpBody<UserInfoBean>> getUserInfo();
}

View File

@ -0,0 +1,34 @@
package com.yutou.bili.bean.login;
import com.alibaba.fastjson2.annotation.JSONField;
import com.google.gson.annotations.SerializedName;
import com.yutou.databases.AbsDatabasesBean;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class LoginCookie extends AbsDatabasesBean {
@JSONField(name = "SESSDATA")
String sessdta;
@JSONField(name = "Path")
String path;
@JSONField(name = "DedeUserID")
String dedeUserID;
@JSONField(name = "DedeUserID__ckMd5")
String dedeUserIDCkMd5;
@JSONField(name = "bili_jct")
String biliJct;
@JSONField(name = "Expires")
String expires;
@JSONField(name = "Domain")
String domain;
@JSONField(name = "sid")
String sid;
@JSONField(name = "gourl")
String gourl;
public LoginCookie() {
setTableName("login_cookie");
}
}

View File

@ -0,0 +1,17 @@
package com.yutou.bili.bean.login;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class LoginInfoBean extends BaseBean {
private String url;
private String refresh_token;
private long timestamp;
private int code;
private String message;
}

View File

@ -0,0 +1,15 @@
package com.yutou.bili.bean.login;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class QRCodeGenerateBean extends BaseBean {
private String url;
private String qrcode_key;
}

View File

@ -0,0 +1,288 @@
package com.yutou.bili.bean.login;
import com.alibaba.fastjson2.annotation.JSONField;
import com.google.gson.annotations.SerializedName;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
@EqualsAndHashCode(callSuper = true)
@Data
public class UserInfoBean extends BaseBean {
@JSONField(name = "isLogin")
private boolean isLogin;
@JSONField(name = "email_verified")
private int emailVerified;
@JSONField(name = "face")
private String face;
@JSONField(name = "face_nft")
private int faceNft;
@JSONField(name = "face_nft_type")
private int faceNftType;
@JSONField(name = "level_info")
private LevelInfo levelInfo;
@JSONField(name = "mid")
private long mid;
@JSONField(name = "mobile_verified")
private int mobileVerified;
@JSONField(name = "money")
private double money;
@JSONField(name = "moral")
private int moral;
@JSONField(name = "official")
private Official official;
@JSONField(name = "officialVerify")
private OfficialVerify officialVerify;
@JSONField(name = "pendant")
private Pendant pendant;
@JSONField(name = "scores")
private int scores;
@JSONField(name = "uname")
private String uname;
@JSONField(name = "vipDueDate")
private Date vipDueDate;
@JSONField(name = "vipStatus")
private int vipStatus;
@JSONField(name = "vipType")
private int vipType;
@JSONField(name = "vip_pay_type")
private int vipPayType;
@JSONField(name = "vip_theme_type")
private int vipThemeType;
@JSONField(name = "vip_label")
private VipLabel vipLabel;
@JSONField(name = "vip_avatar_subscript")
private int vipAvatarSubscript;
@JSONField(name = "vip_nickname_color")
private String vipNicknameColor;
@JSONField(name = "vip")
private Vip vip;
@JSONField(name = "wallet")
private Wallet wallet;
@JSONField(name = "has_shop")
private boolean hasShop;
@JSONField(name = "shop_url")
private String shopUrl;
@JSONField(name = "allowance_count")
private int allowanceCount;
@JSONField(name = "answer_status")
private int answerStatus;
@JSONField(name = "is_senior_member")
private boolean isSeniorMember;
@JSONField(name = "wbi_img")
private WbiImg wbiImg;
@JSONField(name = "is_jury")
private boolean isJury;
// 省略了getters和setters
// level_info的内部数据结构
@Data
public static class LevelInfo {
@JSONField(name = "current_level")
private int currentLevel;
@JSONField(name = "current_min")
private int currentMin;
@JSONField(name = "current_exp")
private int currentExp;
@JSONField(name = "next_exp")
private String nextExp;
// getters and setters
}
// official的结构
@Data
public static class Official {
@JSONField(name = "role")
private int role;
@JSONField(name = "title")
private String title;
@JSONField(name = "desc")
private String desc;
@JSONField(name = "type")
private int type;
// getters and setters
}
// officialVerify的结构
@Data
public static class OfficialVerify {
@JSONField(name = "type")
private int type;
@JSONField(name = "desc")
private String desc;
// getters and setters
}
// pendant的结构
@Data
public static class Pendant {
@JSONField(name = "pid")
private int pid;
@JSONField(name = "name")
private String name;
@JSONField(name = "image")
private String image;
@JSONField(name = "expire")
private int expire;
@JSONField(name = "image_enhance")
private String imageEnhance;
@JSONField(name = "image_enhance_frame")
private String imageEnhanceFrame;
@JSONField(name = "n_pid")
private int nPid;
// getters and setters
}
// vipLabel的结构
@Data
public static class VipLabel {
@JSONField(name = "path")
private String path;
@JSONField(name = "text")
private String text;
@JSONField(name = "label_theme")
private String labelTheme;
@JSONField(name = "text_color")
private String textColor;
@JSONField(name = "bg_style")
private String bgStyle;
@JSONField(name = "bg_color")
private String bgColor;
@JSONField(name = "border_color")
private String borderColor;
@JSONField(name = "use_img_label")
private boolean useImgLabel;
@JSONField(name = "img_label_uri_hans")
private String imgLabelUriHans;
@JSONField(name = "img_label_uri_hant")
private String imgLabelUriHant;
@JSONField(name = "img_label_uri_hans_static")
private String imgLabelUriHansStatic;
@JSONField(name = "img_label_uri_hant_static")
private String imgLabelUriHantStatic;
// getters and setters
}
// vip的结构和vipLabel类似
@Data
public static class Vip {
@JSONField(name = "type")
private int type;
@JSONField(name = "status")
private int status;
@JSONField(name = "due_date")
private Date dueDate;
@JSONField(name = "vip_pay_type")
private int vipPayType;
@JSONField(name = "theme_type")
private int themeType;
@JSONField(name = "label")
private VipLabel label;
@JSONField(name = "avatar_subscript")
private int avatarSubscript;
@JSONField(name = "nickname_color")
private String nicknameColor;
// getters and setters
}
// wallet的结构
@Data
public static class Wallet {
@JSONField(name = "mid")
private long mid;
@JSONField(name = "bcoin_balance")
private int bcoinBalance;
@JSONField(name = "coupon_balance")
private int couponBalance;
@JSONField(name = "coupon_due_time")
private int couponDueTime;
// getters and setters
}
// WbiImg的结构
@Data
public static class WbiImg {
@JSONField(name = "img_url")
private String imgUrl;
@JSONField(name = "sub_url")
private String subUrl;
// getters and setters
}
}

View File

@ -0,0 +1,49 @@
package com.yutou.bili.databases;
import com.yutou.bili.bean.login.LoginCookie;
import com.yutou.databases.SQLiteManager;
import java.util.List;
public class BiliBiliLoginDatabase extends SQLiteManager {
LoginCookie cookie;
private static BiliBiliLoginDatabase instance;
private BiliBiliLoginDatabase(Class<LoginCookie> tClass) {
try {
cookie = new LoginCookie();
} catch (Exception e) {
throw new RuntimeException(e);
}
init();
}
public static BiliBiliLoginDatabase getInstance() {
if (instance == null) {
instance = new BiliBiliLoginDatabase(LoginCookie.class);
}
return instance;
}
public BiliBiliLoginDatabase initData(LoginCookie cookie) {
this.cookie = cookie;
for (BuildSqlTable table : build.getTable()) {
cookie.setTableName(table.getName());
add(cookie);
}
return this;
}
public List<LoginCookie> get() {
return super.get(cookie.getTableName(), LoginCookie.class);
}
@Override
protected LoginCookie getDataBean() {
return new LoginCookie();
}
}
/**
*
*/

View File

@ -0,0 +1,118 @@
package com.yutou.bili.net;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.bili.api.LoginApi;
import com.yutou.bili.bean.login.LoginCookie;
import com.yutou.bili.bean.login.LoginInfoBean;
import com.yutou.bili.bean.login.QRCodeGenerateBean;
import com.yutou.bili.databases.BiliBiliLoginDatabase;
import com.yutou.databases.AbsDatabasesBean;
import com.yutou.okhttp.HttpBody;
import com.yutou.okhttp.HttpCallback;
import com.yutou.okhttp.api.BaseApi;
import okhttp3.Headers;
import org.springframework.util.StringUtils;
import retrofit2.Response;
import java.io.IOException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;
public class BiliLoginNetApiManager extends BaseApi {
public static final int LOGIN_QRCODE = 100;
public static final int LOGIN_SUCCESS = 101;
private static BiliLoginNetApiManager instance;
LoginApi loginApi;
private BiliLoginNetApiManager() {
super("https://passport.bilibili.com");
loginApi = createApi(LoginApi.class);
}
public static BiliLoginNetApiManager getInstance() {
if (instance == null) {
instance = new BiliLoginNetApiManager();
}
return instance;
}
public void login(HttpCallback<LoginCookie> callback) {
List<LoginCookie> cookie = BiliBiliLoginDatabase.getInstance().get();
if (!cookie.isEmpty()) {
callback.onResponse(null, LOGIN_SUCCESS, null, cookie.get(0), null);
return;
}
loginApi.getQRCodeGenerate().enqueue(new HttpCallback<QRCodeGenerateBean>() {
@Override
public void onResponse(Headers headers, int code, String status, QRCodeGenerateBean response, String rawResponse) {
String oauthKey = response.getQrcode_key();
String url = response.getUrl();
String bd = "gourl=https%3A%2F%2Fpassport.bilibili.com%2Fajax%2FminiLogin%2Fredirect&oauthKey=" + oauthKey;
callback.onResponse(headers, LOGIN_QRCODE, null, null, url);
new Thread(() -> waitLogin(oauthKey, callback)).start();
}
@Override
public void onFailure(Throwable throwable) {
}
});
}
private void waitLogin(String oauthKey, HttpCallback<LoginCookie> callback) {
long time = System.currentTimeMillis();
new Timer().schedule(new TimerTask() {
@Override
public void run() {
String bd = "gourl=https%3A%2F%2Fpassport.bilibili.com%2Fajax%2FminiLogin%2Fredirect&oauthKey=" + oauthKey;
if ((System.currentTimeMillis() - time) > 5 * 60 * 1000) {
cancel();
return;
}
try {
Response<HttpBody<LoginInfoBean>> response = loginApi.loginQRCode(oauthKey).execute();
Headers headers = response.headers();
HttpBody<LoginInfoBean> httpBody = response.body();
if (httpBody.getData().getCode() == 0) {
JSONObject ck = new JSONObject();
List<String> list = headers.values("set-cookie");
for (String cookie : list) {
String[] split = cookie.split(";");
for (String string : split) {
if (!ck.containsKey(string) && !StringUtils.isEmpty(string) && string.contains("=")) {
String key = string.split("=")[0].trim();
String value = string.split("=")[1].trim();
if (key.contains("Expires")) {
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMMM yyyy HH:mm:ss z", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getDefault());
Date date = sdf.parse(value, new ParsePosition(0));
value = String.valueOf(date.getTime() / 1000);
}
ck.put(key, value);
}
}
}
if (!list.isEmpty()) {
ck.put("gourl", bd);
LoginCookie cookie = JSONObject.parseObject(ck.toString(), LoginCookie.class);
cancel();
callback.onResponse(headers, LOGIN_SUCCESS, "ok", cookie, ck.toString());
} else {
callback.onFailure(new RuntimeException("cookie为空"));
cancel();
}
}
} catch (IOException e) {
cancel();
throw new RuntimeException(e);
}
}
}, 1000, 3000);
}
}

View File

@ -0,0 +1,47 @@
package com.yutou.bili.net;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.bili.api.UserApi;
import com.yutou.bili.bean.login.LoginCookie;
import com.yutou.bili.databases.BiliBiliLoginDatabase;
import com.yutou.inter.IHttpApiCheckCallback;
import com.yutou.okhttp.api.BaseApi;
import java.util.HashMap;
import java.util.List;
public class BiliUserNetApiManager extends BaseApi {
public static final int LOGIN_LOGOUT = 1;
public static BiliUserNetApiManager manager;
private BiliUserNetApiManager() {
super("https://api.bilibili.com");
}
public static BiliUserNetApiManager getInstance() {
if (manager == null) {
manager = new BiliUserNetApiManager();
}
return manager;
}
public void getUserApi(IHttpApiCheckCallback<UserApi> callback) {
List<LoginCookie> list = BiliBiliLoginDatabase.getInstance().get();
if (!list.isEmpty()) {
HashMap<String, String> headers = new HashMap<>();
LoginCookie cookie = list.get(0);
JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(cookie));
StringBuilder ck=new StringBuilder();
for (String key : json.keySet()) {
ck.append(key).append("=").append(json.getString(key)).append("; ");
}
headers.put("Cookie", ck.toString());
setHeaders(headers);
callback.onSuccess(createApi(UserApi.class));
} else {
callback.onError(LOGIN_LOGOUT, "未登录");
}
}
}

34
common/pom.xml Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yutou</groupId>
<artifactId>bilibili</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,17 @@
package com.yutou.databases;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import lombok.Data;
@Data
public class AbsDatabasesBean {
String tableName;
public JSONObject toJson() {
JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(this, JSONWriter.Feature.WriteMapNullValue));
json.remove("tableName");
return json;
}
}

View File

@ -0,0 +1,302 @@
package com.yutou.databases;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.utils.Log;
import lombok.Data;
import lombok.Getter;
import java.io.File;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public abstract class SQLiteManager {
protected Connection conn;
private String url = "jdbc:sqlite:";
private File sql;
@Getter
public BuildSql build;
public void init() {
AbsDatabasesBean data = getDataBean();
List<BuildSqlItem> items = new ArrayList<>();
Field[] fields = data.getClass().getDeclaredFields();
for (Field field : fields) {
String name = field.getAnnotation(JSONField.class).name();
if (name.equals("tableName")) continue;
String type = BuildSqlItem.TYPE_STRING;
if (field.getType() == int.class) {
type = BuildSqlItem.TYPE_INT;
} else if (field.getType() == String.class) {
type = BuildSqlItem.TYPE_STRING;
} else if (field.getType() == Date.class) {
type = BuildSqlItem.TYPE_TIME;
}
items.add(BuildSqlItem.create().setName(name).setType(type).setNull(true).setKey(false));
}
BuildSql sql = BuildSql.create()
.setFileName("bilibili_login.db")
.setTable(BuildSqlTable.create().setName(data.getTableName()).setItem(items));
build(sql);
}
public void startBatch() {
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
Log.e(e);
}
}
public void closeBatch() {
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
Log.e(e);
}
}
public void close() {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
public void commit() {
try {
conn.commit();
} catch (SQLException e) {
Log.e(e);
}
}
public <T extends AbsDatabasesBean> void add(T t) {
try {
Statement statement = conn.createStatement();
StringBuilder sb = new StringBuilder();
StringBuilder value = new StringBuilder();
sb.append("INSERT INTO `").append(t.getTableName()).append("` ");
sb.append("(");
value.append("(");
for (String key : t.toJson().keySet()) {
sb.append("`").append(key).append("`,");
value.append("'").append(t.toJson().get(key)).append("',");
}
sb.deleteCharAt(sb.length() - 1);
value.deleteCharAt(value.length() - 1);
value.append(")");
sb.append(") VALUES ");
sb.append(value);
statement.executeUpdate(sb.toString());
statement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public <T extends AbsDatabasesBean> List<T> get(String table, Class<T> tClass) {
List<T> list = new ArrayList<>();
try {
Statement statement = conn.createStatement();
String sql = "SELECT * FROM `" + table + "`";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
JSONObject json = new JSONObject();
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
String name = resultSet.getMetaData().getColumnName(i + 1);
json.put(name, resultSet.getObject(name));
}
list.add(json.to(tClass));
}
resultSet.close();
statement.closeOnCompletion();
} catch (Exception e) {
throw new RuntimeException(e);
}
return list;
}
private void createSql(BuildSql build) {
try {
sql.mkdirs();
sql.delete();
conn = DriverManager.getConnection(url + sql.getAbsolutePath());
} catch (Exception e) {
Log.e(e);
}
startBatch();
for (BuildSqlTable table : build.getTable()) {
Log.i("创建表:" + table.getName());
createSqlOfTable(table);
}
closeBatch();
}
private void createSqlOfTable(BuildSqlTable table) {
String tableName = table.getName();
try {
Statement statement = conn.createStatement();
List<BuildSqlItem> items = table.getItem();
StringBuilder sql = new StringBuilder();
sql.append("CREATE TABLE `")
.append(tableName)
.append("` (");
for (BuildSqlItem item : items) {
StringBuilder builder = new StringBuilder();
String type = switch (item.getType()) {
case "int" -> " INTEGER ";
case "TIME" -> " NUMERIC ";
default -> " TEXT ";
};
builder.append("`")
.append(item.getName())
.append("`")
.append(type)
.append(item.isNull() ? "" : " NOT NULL ")
.append(item.isKey() ? " PRIMARY KEY AUTOINCREMENT " : "")
.append(",");
sql.append(builder.toString());
}
sql.append(");");
System.out.println("创建表 > " + sql.toString());
statement.execute(sql.toString().replace(",);", ");"));
statement.closeOnCompletion();
} catch (Exception e) {
Log.e(e);
}
}
protected void build(BuildSql buildSql) {
try {
this.build = buildSql;
Class.forName("org.sqlite.JDBC");
sql = new File("databases" + File.separator + buildSql.getFileName());
if (!sql.exists()) {
createSql(buildSql);
} else {
conn = DriverManager.getConnection(url + sql.getAbsolutePath());
}
} catch (Exception e) {
Log.e(e);
}
}
public boolean setDB(String fileName) {
try {
Class.forName("org.sqlite.JDBC");
sql = new File("db" + File.separator + fileName);
if (sql.exists()) {
if (conn != null && !conn.isClosed()) {
conn.close();
}
conn = DriverManager.getConnection(url + sql.getAbsolutePath());
return true;
}
} catch (Exception e) {
Log.e(e);
}
return false;
}
protected abstract AbsDatabasesBean getDataBean();
public static void main(String[] args) {
}
@Data
public static class BuildSql {
String fileName;
List<BuildSqlTable> table;
public static BuildSql create() {
return new BuildSql();
}
public BuildSql setFileName(String fileName) {
this.fileName = fileName;
return this;
}
public BuildSql setTable(List<BuildSqlTable> table) {
this.table = table;
return this;
}
public BuildSql setTable(BuildSqlTable... table) {
this.table = List.of(table);
return this;
}
}
@Data
public static class BuildSqlTable {
String name;
List<BuildSqlItem> item;
public static BuildSqlTable create() {
return new BuildSqlTable();
}
public BuildSqlTable setName(String name) {
this.name = name;
return this;
}
public BuildSqlTable setItem(List<BuildSqlItem> item) {
this.item = item;
return this;
}
public BuildSqlTable setItem(BuildSqlItem... item) {
this.item = List.of(item);
return this;
}
}
@Data
public static class BuildSqlItem {
public static final String TYPE_INT = "init";
public static final String TYPE_STRING = "String";
public static final String TYPE_TIME = "TIME";
String name;
String type;
boolean isNull;
boolean isKey;
public static BuildSqlItem create() {
return new BuildSqlItem();
}
public BuildSqlItem setName(String name) {
this.name = name;
return this;
}
public BuildSqlItem setType(String type) {
this.type = type;
return this;
}
public BuildSqlItem setNull(boolean aNull) {
isNull = aNull;
return this;
}
public BuildSqlItem setKey(boolean key) {
isKey = key;
return this;
}
}
}

View File

@ -0,0 +1,7 @@
package com.yutou.inter;
public interface IHttpApiCheckCallback<T> {
void onSuccess(T api);
void onError(int code, String error);
}

View File

@ -0,0 +1,6 @@
package com.yutou.okhttp;
import java.io.Serializable;
public class BaseBean implements Serializable {
}

View File

@ -0,0 +1,32 @@
package com.yutou.okhttp;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Request;
import java.util.HashMap;
public class GetRequestParams implements IRequestParam {
/**
* 构建Request
*
* @param request
* @return
*/
@Override
public Request getRequest(HashMap<String, String> headerMap, HashMap<String, String> map, Request request) {
Headers.Builder headerBuild = request.headers().newBuilder();
if (!headerMap.isEmpty()) {
for (String key : headerMap.keySet()) {
headerBuild.add(key, headerMap.get(key));
}
}
//添加公共参数
HttpUrl.Builder builder = request.url().newBuilder();
for (String key : map.keySet()) {
builder.addQueryParameter(key, String.valueOf(map.get(key)));
}
return request.newBuilder().url(builder.build()).headers(headerBuild.build()).build();
}
}

View File

@ -0,0 +1,14 @@
package com.yutou.okhttp;
import lombok.Data;
@Data
public class HttpBody<T> {
private String msg;
private String status;
private int code;
private int retcode;
private T data;
private String src;
}

View File

@ -0,0 +1,35 @@
package com.yutou.okhttp;
import okhttp3.Headers;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public abstract class HttpCallback<T> implements Callback<HttpBody<T>> {
public abstract void onResponse(Headers headers,int code, String status, T response, String rawResponse);
public abstract void onFailure(Throwable throwable);
@Override
public void onResponse(Call<HttpBody<T>> call, Response<HttpBody<T>> response) {
if (response.body() != null) {
onResponse(
response.headers(),
response.body().getRetcode(),
response.body().getStatus(),
response.body().getData(),
response.body().getSrc()
);
} else {
onFailure(new NullPointerException("response body is null"));
}
call.cancel();
}
@Override
public void onFailure(Call<HttpBody<T>> call, Throwable throwable) {
onFailure(throwable);
call.cancel();
}
}

View File

@ -0,0 +1,209 @@
package com.yutou.okhttp;
import com.yutou.utils.Log;
import okhttp3.*;
import okhttp3.internal.http.HttpHeaders;
import okio.Buffer;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
public class HttpLoggingInterceptor implements Interceptor {
private static final String TAG = "HttpLogging";
private static final Charset UTF8 = Charset.forName("UTF-8");
private volatile Level printLevel = Level.NONE;
private java.util.logging.Level colorLevel;
private Logger logger;
private static boolean prLog;
public static void setLog(boolean log) {
prLog = log;
}
public enum Level {
NONE, //不打印log
BASIC, //只打印 请求首行 响应首行
HEADERS, //打印请求和响应的所有 Header
BODY //所有数据全部打印
}
public HttpLoggingInterceptor(String tag) {
logger = Logger.getLogger(tag);
colorLevel = java.util.logging.Level.INFO;
}
public void setPrintLevel(Level level) {
if (printLevel == null)
throw new NullPointerException("printLevel == null. Use Level.NONE instead.");
printLevel = level;
}
public void setColorLevel(java.util.logging.Level level) {
colorLevel = level;
}
private void log(String message) {
//logger.log(colorLevel, message);
if (prLog) {
Log.i(TAG, message);
}
//Log.e(TAG,message);
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (request.body() != null && request.body().contentLength() == 0) {
request = chain.call().request();
}
if (printLevel == Level.NONE) {
return chain.proceed(request);
}
//请求日志拦截
logForRequest(request, chain.connection());
//执行请求计算请求时间
long startNs = System.nanoTime();
Response response;
try {
response = chain.proceed(request);
} catch (Exception e) {
log("<-- HTTP FAILED: " + e);
throw e;
}
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
//响应日志拦截
return logForResponse(response, tookMs);
}
private void logForRequest(Request request, Connection connection) throws IOException {
boolean logBody = (printLevel == Level.BODY);
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
RequestBody requestBody = request.body();
boolean hasRequestBody = requestBody != null;
Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
try {
String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol;
log(requestStartMessage);
if (logHeaders) {
if (hasRequestBody) {
// Request body headers are only present when installed as a network interceptor. Force
// them to be included (when available) so there values are known.
if (requestBody.contentType() != null) {
log("\tContent-Type: " + requestBody.contentType());
}
if (requestBody.contentLength() != -1) {
log("\tContent-Length: " + requestBody.contentLength());
}
}
Headers headers = request.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
String name = headers.name(i);
// Skip headers from the request body as they are explicitly logged above.
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
log("\t" + name + ": " + headers.value(i));
}
}
log(" ");
if (logBody && hasRequestBody) {
if (isPlaintext(requestBody.contentType())) {
bodyToString(request);
} else {
log("\tbody: maybe [binary body], omitted!");
}
}
}
} catch (Exception e) {
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
} finally {
log("--> END " + request.method());
}
}
private Response logForResponse(Response response, long tookMs) {
Response.Builder builder = response.newBuilder();
Response clone = builder.build();
ResponseBody responseBody = clone.body();
boolean logBody = (printLevel == Level.BODY);
boolean logHeaders = (printLevel == Level.BODY || printLevel == Level.HEADERS);
try {
log("<-- " + clone.code() + ' ' + clone.message() + ' ' + clone.request().url() + " (" + tookMs + "ms");
if (logHeaders) {
Headers headers = clone.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
log("\t" + headers.name(i) + ": " + headers.value(i));
}
log(" ");
if (logBody && HttpHeaders.hasBody(clone)) {
if (responseBody == null) return response;
if (isPlaintext(responseBody.contentType())) {
byte[] bytes = responseBody.byteStream().readAllBytes();
MediaType contentType = responseBody.contentType();
String body = new String(bytes, getCharset(contentType));
log("\tbody:" + body);
responseBody = ResponseBody.create(responseBody.contentType(), bytes);
return response.newBuilder().body(responseBody).build();
} else {
log("\tbody: maybe [binary body], omitted!");
}
}
}
} catch (Exception e) {
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
} finally {
log("<-- END HTTP");
}
return response;
}
private static Charset getCharset(MediaType contentType) {
Charset charset = contentType != null ? contentType.charset(UTF8) : UTF8;
if (charset == null) charset = UTF8;
return charset;
}
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
private static boolean isPlaintext(MediaType mediaType) {
if (mediaType == null) return false;
if (mediaType.type() != null && mediaType.type().equals("text")) {
return true;
}
String subtype = mediaType.subtype();
if (subtype != null) {
subtype = subtype.toLowerCase();
if (subtype.contains("x-www-form-urlencoded") || subtype.contains("json") || subtype.contains("xml") || subtype.contains("html")) //
return true;
}
return false;
}
private void bodyToString(Request request) {
try {
Request copy = request.newBuilder().build();
RequestBody body = copy.body();
if (body == null) return;
Buffer buffer = new Buffer();
body.writeTo(buffer);
Charset charset = getCharset(body.contentType());
log("\tbody:" + buffer.readString(charset));
} catch (Exception e) {
logger.log(java.util.logging.Level.WARNING, e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,9 @@
package com.yutou.okhttp;
import okhttp3.Request;
import java.util.HashMap;
public interface IRequestParam {
Request getRequest(HashMap<String,String> header, HashMap<String,String> map, Request request);
}

View File

@ -0,0 +1,43 @@
package com.yutou.okhttp;
import okhttp3.Request;
import java.util.HashMap;
public class ParamsContext {
private IRequestParam iRequestParam;
private Request request;
private HashMap<String, String> map;
private HashMap<String, String> headerMap;
public ParamsContext(HashMap<String, String> map, Request request) {
if (map == null) {
map = new HashMap<>();
}
this.map = map;
this.request = request;
this.headerMap = new HashMap<>();
}
public ParamsContext(HashMap<String, String> headerMap, HashMap<String, String> map, Request request) {
if (map == null) {
map = new HashMap<>();
}
this.map = map;
this.request = request;
this.headerMap = headerMap;
}
public Request getInRequest() {
switch (request.method()) {
case "GET":
iRequestParam = new GetRequestParams();
break;
case "POST":
iRequestParam = new PostRequestParams();
break;
}
headerMap.remove("tableName");
return iRequestParam.getRequest(headerMap, map, request);
}
}

View File

@ -0,0 +1,73 @@
package com.yutou.okhttp;
import com.alibaba.fastjson2.JSONObject;
import okhttp3.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class PostRequestParams implements IRequestParam {
@Override
public Request getRequest(HashMap<String, String> headerMap, HashMap<String, String> map, Request request) {
Headers.Builder headerBuilder = request.headers().newBuilder();
if (!headerMap.isEmpty()) {
for (String key : headerMap.keySet()) {
headerBuilder.add(key, headerMap.get(key));
}
}
if (request.body() instanceof FormBody) {
FormBody.Builder bodyBuilder = new FormBody.Builder();
FormBody formBody = (FormBody) request.body();
for (int i = 0; i < formBody.size(); i++) {
bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
}
for (String key : map.keySet()) {
bodyBuilder.addEncoded(key, String.valueOf(map.get(key)));
}
formBody = bodyBuilder.build();
request = request.newBuilder().headers(headerBuilder.build()).post(formBody).build();
} else if (request.body() != null) {
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), toUrlParams(map));
request = request.newBuilder()
.headers(headerBuilder.build())
.post(request.body())
.post(requestBody).build();
}
return request;
}
public static String toUrlParams(JSONObject json) {
StringBuilder string = new StringBuilder();
Set<String> keys = json.keySet();
for (String key : keys) {
try {
string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key), "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
try {
string.append("&").append(URLEncoder.encode(key, "UTF-8")).append("=");
// string += "&" + key + "=";
} catch (Exception e1) {
string.append("&").append(key).append("=");
}
}
}
string = new StringBuilder(string.substring(1, string.length()).replaceAll(" ", ""));
return string.toString();
}
public static String toUrlParams(Map<String, String> map) {
if (map.isEmpty()) {
return "";
}
StringBuilder builder = new StringBuilder();
for (String key : map.keySet()) {
builder.append(key).append("=").append(map.get(key)).append("&");
}
return builder.substring(0, builder.length() - 1);
}
}

View File

@ -0,0 +1,107 @@
package com.yutou.okhttp.api;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.bind.DateTypeAdapter;
import com.yutou.okhttp.HttpLoggingInterceptor;
import com.yutou.okhttp.ParamsContext;
import com.yutou.okhttp.converter.JsonCallAdapter;
import com.yutou.okhttp.converter.JsonConverterFactory;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.CallAdapter;
import retrofit2.Converter;
import retrofit2.Retrofit;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
public class BaseApi {
private String URL;
private HashMap<String, String> params;
private HashMap<String, String> headers;
public BaseApi(String URL) {
this.URL = URL;
}
public BaseApi setURL(String URL) {
this.URL = URL;
return this;
}
public BaseApi setHeaders(HashMap<String, String> headers) {
this.headers = headers;
return this;
}
public BaseApi setParams(HashMap<String, String> params) {
this.params = params;
return this;
}
/**
* 创建一个接口方法
*
* @param okHttpClient okhttp客户端
* @param converterFactory 处理工厂类
* @param callAdapterFactory 请求适配器工厂
* @param baseUrl 基础地质
* @param service 接口
* @param <T> 接口泛型
* @return 接口
*/
public <T> T create(OkHttpClient okHttpClient, Converter.Factory converterFactory, CallAdapter.Factory callAdapterFactory, String baseUrl, Class<T> service) {
Retrofit.Builder builder = new Retrofit.Builder()
//基础url
.baseUrl(baseUrl)
//客户端OKHttp
.client(okHttpClient);
//添加转换工厂
if (null != converterFactory) {
builder.addConverterFactory(converterFactory);
}
//添加请求工厂
if (null != callAdapterFactory) {
builder.addCallAdapterFactory(callAdapterFactory);
}
//创建retrofit对象
Retrofit retrofit = builder.build();
//返回创建的api
return retrofit.create(service);
}
public <T> T createApi(Class<T> apiClass) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new DateTypeAdapter())
.create();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("http");
loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient()
.newBuilder()
.addInterceptor(initQuery())
.addInterceptor(loggingInterceptor);
return create(builder.build(),
JsonConverterFactory.create(gson),
JsonCallAdapter.create(),
URL,
apiClass);
}
public Interceptor initQuery() {
Interceptor addQueryParameterInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//配置公共参数
request = new ParamsContext(headers,params,request).getInRequest();
return chain.proceed(request);
}
};
return addQueryParameterInterceptor;
}
}

View File

@ -0,0 +1,19 @@
package com.yutou.okhttp.converter;
import org.jetbrains.annotations.Nullable;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
public class JsonCallAdapter extends CallAdapter.Factory{
public static JsonCallAdapter create(){
return new JsonCallAdapter();
}
@Nullable
@Override
public CallAdapter<?, ?> get(Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
}

View File

@ -0,0 +1,40 @@
package com.yutou.okhttp.converter;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import org.jetbrains.annotations.Nullable;
import retrofit2.Converter;
import retrofit2.Retrofit;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
public class JsonConverterFactory extends Converter.Factory {
Gson gson;
public static JsonConverterFactory create(Gson gson) {
return new JsonConverterFactory(gson);
}
private JsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Nullable
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
// return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new JsonRequestBodyConverter<>(gson,adapter);
}
@Nullable
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
// return super.responseBodyConverter(type, annotations, retrofit);
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new JsonResponseBodyConverter<>(gson,adapter,type);
}
}

View File

@ -0,0 +1,36 @@
package com.yutou.okhttp.converter;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonWriter;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import org.jetbrains.annotations.Nullable;
import retrofit2.Converter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
public class JsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
Gson gson;
TypeAdapter<T> adapter;
public JsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson=gson;
this.adapter=adapter;
}
@Nullable
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), StandardCharsets.UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
byte[] bytes = buffer.readByteArray();
return RequestBody.create(MediaType.parse("application/json; charset=UTF-8"),bytes );
}
}

View File

@ -0,0 +1,45 @@
package com.yutou.okhttp.converter;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.yutou.okhttp.HttpBody;
import okhttp3.ResponseBody;
import org.jetbrains.annotations.Nullable;
import retrofit2.Converter;
import java.io.IOException;
import java.lang.reflect.Type;
public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
Gson gson;
TypeAdapter<?> adapter;
Type type;
public JsonResponseBodyConverter(Gson gson, TypeAdapter<?> adapter, Type type) {
this.gson = gson;
this.adapter = adapter;
this.type = type;
}
@Nullable
@Override
public T convert(ResponseBody responseBody) throws IOException {
String string = new String(responseBody.bytes());
responseBody.close();
HttpBody<T> body;
try {
body = JSONObject.parseObject(string, type, JSONReader.Feature.FieldBased);
body.setSrc(string);
return (T) body;
} catch (Exception e) {
e.printStackTrace();
body = new HttpBody();
body.setSrc(string);
}
return (T) body;
}
}

View File

@ -1,15 +1,16 @@
package com.yutou.bilibili.Tools;
package com.yutou.utils;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.xml.bind.DatatypeConverter;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.net.URLEncoder;
import java.security.MessageDigest;
@ -26,7 +27,7 @@ public class AppTools {
writer.close();
return true;
} catch (IOException e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
return false;
}
}
@ -166,7 +167,7 @@ public class AppTools {
public static String deleteCookie(HttpServletRequest request, HttpServletResponse response, String key) {
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals(key)) {
com.yutou.bilibili.Tools.Log.i("删除key=" + key);
Log.i("删除key=" + key);
cookie.setMaxAge(0);
cookie.setPath("/");
cookie.setValue(null);
@ -249,7 +250,7 @@ public class AppTools {
digest.update(data.getBytes());
return DatatypeConverter.printHexBinary(digest.digest());
} catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
}
return "";
}
@ -278,7 +279,7 @@ public class AppTools {
}else{
if(srcFileName.equals("Activity.smali")){
com.yutou.bilibili.Tools.Log.i("文件夹已存在:"+destFileName);
Log.i("文件夹已存在:"+destFileName);
}
}
@ -302,10 +303,10 @@ public class AppTools {
in.close();
return true;
} catch (FileNotFoundException e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
return false;
} catch (IOException e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
return false;
}
}

View File

@ -0,0 +1,34 @@
package com.yutou.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
public class Base64Tools {
public static String encode(String str) {
return Base64.getEncoder().encodeToString(str.getBytes());
}
public static String decode(String str) {
return new String(Base64.getDecoder().decode(str));
}
public static String encode(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
public static String encode(File file) {
try {
byte[] fileContent = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
return encode(fileContent);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
}
}

View File

@ -1,6 +1,7 @@
package com.yutou.bilibili.Tools;
package com.yutou.utils;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSONObject;
import java.io.*;
@ -11,6 +12,10 @@ public class ConfigTools {
public static final String CONFIG="config.json";
public static final String DATA="data.json";
public static final String SQLITE="sqlite.json";
public static final String NAPCAT_URL = "napcat.url";
public static final String QQ = "qq_bot";
static {
try {
File file=new File(CONFIG);
@ -23,7 +28,7 @@ public class ConfigTools {
}
file=null;
}catch (Exception e){
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
}
}
@ -68,7 +73,7 @@ public class ConfigTools {
writer.close();
return true;
} catch (IOException e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
return false;
}
}
@ -84,7 +89,7 @@ public class ConfigTools {
return str.toString();
} catch (Exception e) {
Log.i("error = "+file.getAbsolutePath());
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
}
return null;
}

View File

@ -1,4 +1,4 @@
package com.yutou.bilibili.Tools;
package com.yutou.utils;
import java.io.File;
@ -13,8 +13,9 @@ public class Log {
public static void i(String tag, Object log) {
i('[' + tag + ']' + log);
}
public static void i(Object log) {
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout"))) {
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logcat"))) {
return;
}
System.out.printf("[%s]%s%n",
@ -25,7 +26,7 @@ public class Log {
}
public static void e(Exception e) {
if (!((boolean) ConfigTools.load(ConfigTools.CONFIG, "logout"))) {
if (!ConfigTools.load(ConfigTools.CONFIG, "logcat", Boolean.class)){
return;
}
i(e.getMessage());
@ -34,7 +35,7 @@ public class Log {
public static void i(String timer, int roomId, Object log) {
String logFlag = RedisTools.get("live-log", 1);
if (logFlag!=null&&logFlag.startsWith("true")) {
if (logFlag != null && logFlag.startsWith("true")) {
if (logFlag.contains("|")) {
if (log.toString().contains(logFlag.split("\\|")[1])) {
getLogger("[" + timer.replace(":", "_") + "]" + roomId).log(Level.INFO, log.toString());

View File

@ -1,21 +1,19 @@
package com.yutou.bilibili.Tools;
package com.yutou.utils;
import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.QQBot.QQBotManager;
import com.alibaba.fastjson2.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisPubSub;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.Set;
public class RedisTools {
public static final int QQBOT_USER = 3;
private static boolean isNotInstallRedis = false;
private static String host;
private static int port;
@ -51,8 +49,8 @@ public class RedisTools {
return true;
}
public static boolean set(String key, String value) {
return set(0, key, value);
public static boolean set(Object key, String value) {
return set(0, key.toString(), value);
}
public static boolean set(String key, String value, int timeout) {
@ -91,12 +89,12 @@ public class RedisTools {
return value;
}
public static String get(String key) {
return get(key, 0);
public static String get(Object key) {
return get(key.toString(), 0);
}
public static boolean remove(String key) {
return remove(key,0);
public static boolean remove(Object key) {
return remove(key.toString(),0);
}
public static void removeLoginState(String uid) {
@ -117,12 +115,12 @@ public class RedisTools {
return tmp;
}
public static boolean exists(String key, String value) {
public static boolean exists(Object key, String value) {
if (isNotInstallRedis) {
return false;
}
Jedis jedis = getRedis();
boolean flag = value.equals(jedis.get(key));
boolean flag = value.equals(jedis.get(key.toString()));
jedis.close();
return flag;
}
@ -183,53 +181,7 @@ public class RedisTools {
private static boolean init = false;
public static void initRedisPoolSub() {
if (init)
return;
init = true;
Log.i("初始化订阅");
new Thread(new Runnable() {
@Override
public void run() {
Jedis jedis = getPoolRedis();
if (jedis != null)
jedis.psubscribe(new Consumer(), "*");
}
}).start();
}
protected static class Consumer extends JedisPubSub {
@Override
public void onPMessage(String pattern, String channel, String message) {
super.onPMessage(pattern, channel, message);
Log.i("onPMessage: channel=" + channel + " msg=" + message + " pattern=" + pattern);
switch (channel) {
case "bot":
bot(message);
break;
}
}
@Override
public void onMessage(String channel, String message) {
super.onMessage(channel, message);
Log.i("onMessage: channel=" + channel + " msg=" + message);
}
public static void bot(String value) {
switch (value) {
case "getip":
JSONObject json = JSONObject.parseObject(HttpTools.get("https://api.asilu.com/ip/"));
String ip = json.getString("ip");
QQBotManager.getInstance().sendMessage("服务器IP:\n" + ip);
break;
}
}
}
public static void main(String[] args) {
RedisTools.pullMsg("msg", "abc");
}

65
pom.xml
View File

@ -5,16 +5,22 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yutou</groupId>
<artifactId>bilibili</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>bilibili</name>
<description>Demo project for Spring Boot</description>
<modules>
<module>biliapi</module>
<module>qqbot</module>
<module>common</module>
</modules>
<properties>
<java.version>1.8</java.version>
<java.version>21</java.version>
<kotlin.version>1.6.10</kotlin.version>
</properties>
<dependencies>
@ -26,9 +32,9 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
@ -52,9 +58,9 @@
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.22</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
@ -64,18 +70,13 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>annotationProcessor</scope>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.2</version>
</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>
@ -103,27 +104,25 @@
<version>4.1.2</version>
</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 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>com.yutou</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yutou</groupId>
<artifactId>qqbot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
@ -190,6 +189,14 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>7</source>
<target>7</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>

29
qqbot/pom.xml Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yutou</groupId>
<artifactId>bilibili</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>qqbot</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- <dependency>
<groupId>com.yutou</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>-->
</dependencies>
</project>

View File

@ -0,0 +1,57 @@
package com.yutou.napcat;
import com.yutou.napcat.handle.MessageHandleBuild;
import com.yutou.napcat.handle.Text;
import com.yutou.napcat.http.NapCatApi;
import com.yutou.napcat.model.SendMessageResponse;
import com.yutou.okhttp.HttpCallback;
import okhttp3.Headers;
import java.io.File;
public class NapCatQQ {
private NapCatQQ() {
}
public static void main(String[] args) {
/* List<BaseHandle<?>> list = new ArrayList<>();
list.add(new Text("1", false));
list.add(new Text("2", false));
list.add(new Text("3"));
list.add(new Text("4", false));
list.add(new At(583819556L));
list.add(new Text("5"));
QQBotManager.getInstance().sendMessage(false, 891655174L, list);*/
NapCatApi.setLog(false);
File file = new File("C:\\Users\\58381\\Downloads\\0074TT8Yly1hp5mqidwqeg30g20f27wh.gif");
NapCatApi.getMessageApi().sendPrivateMsg(
MessageHandleBuild.create()
.setQQNumber(583819556L)
//.add(new Image(file))
.add(new Text("abc"))
.build()
).enqueue(new HttpCallback<SendMessageResponse>() {
@Override
public void onResponse(Headers headers, int code, String status, SendMessageResponse response, String rawResponse) {
System.out.println("code = " + code + ", status = " + status + ", response = " + response + ", rawResponse = " + rawResponse);
}
@Override
public void onFailure(Throwable throwable) {
throwable.printStackTrace();
}
});
}
/**
* 私聊
{"self_id":240828363,"user_id":583819556,"time":1714472684,"message_id":376,"real_id":376,"message_type":"private","sender":{"user_id":583819556,"nickname":"魔芋","card":""},"raw_message":"123","font":14,"sub_type":"friend","message":[{"data":{"text":"123"},"type":"text"}],"message_format":"array","post_type":"message"}
*/
/**
* 群聊
* {"self_id":240828363,"user_id":583819556,"time":1714472695,"message_id":377,"real_id":377,"message_type":"group","sender":{"user_id":583819556,"nickname":"魔芋","card":"","role":"owner"},"raw_message":"222","font":14,"sub_type":"normal","message":[{"data":{"text":"222"},"type":"text"}],"message_format":"array","post_type":"message","group_id":891655174}
*/
}

View File

@ -0,0 +1,54 @@
package com.yutou.napcat;
import com.yutou.napcat.model.FriendBean;
import com.yutou.napcat.model.GroupBean;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class QQDatabase {
private static Map<Long, Object> data = new HashMap<>();
@Getter
@Setter
private static FriendBean me;
public static void addUser(Long qq, FriendBean bean) {
data.put(qq, bean);
}
public static void addGroup(Long qq, GroupBean bean) {
data.put(qq, bean);
}
public static boolean checkFriend(Long qq) {
if (data.containsKey(qq)) {
return data.get(qq) instanceof FriendBean;
}
return false;
}
public static boolean checkGroup(Long qq) {
if (data.containsKey(qq)) {
return data.get(qq) instanceof GroupBean;
}
return false;
}
public static List<GroupBean> getGroups() {
List<GroupBean> numbers = new ArrayList<>();
for (Long qq : data.keySet()) {
if (data.get(qq) instanceof GroupBean) {
{
numbers.add((GroupBean) data.get(qq));
}
}
}
return numbers;
}
}

View File

@ -0,0 +1,145 @@
package com.yutou.napcat;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.utils.RedisTools;
import redis.clients.jedis.Jedis;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class QQNumberManager {
private static QQNumberManager manager;
private QQNumberManager(){
}
public static QQNumberManager getManager() {
if(manager==null) {
manager=new QQNumberManager();
}
return manager;
}
public void addNumber(Long qq,boolean isGroup){
if(RedisTools.exists(qq,null)){
return;
}
JSONObject json=new JSONObject();
json.put("group",isGroup);
json.put("power",new JSONArray());
json.put("model",new JSONArray());
RedisTools.set(qq,json.toJSONString());
}
public List<Long> getNumber(){
List<Long> list =new ArrayList<>();
Jedis jedis=RedisTools.getRedis();
jedis.select(RedisTools.QQBOT_USER);
Set<String> set=jedis.keys("*");
for (String s : set) {
try {
list.add(Long.parseLong(s));
}catch (Exception ignored){
}
}
jedis.close();
return list;
}
public boolean addPower(Long qq, String power){
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("power");
array.add(power);
json.put("power",array);
return RedisTools.set(qq,json.toJSONString());
}
return false;
}
public List<String> getPower(Long qq){
List<String> list=new ArrayList<>();
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("power");
for (Object power : array) {
list.add((String) power);
}
return list;
}
return list;
}
public List<String> getUseModel(long qq) {
List<String> list=new ArrayList<>();
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("model");
for (Object power : array) {
list.add((String) power);
}
return list;
}
return list;
}
public boolean delPower(Long qq, String power){
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("power");
array.remove(power);
json.put("power",array);
return RedisTools.set(qq,json.toJSONString());
}
return false;
}
public boolean addUseModel(Long qq,Class<?> modelClass){
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("model");
array.add(modelClass.getName());
json.put("model",array);
return RedisTools.set(qq,json.toJSONString());
}
return false;
}
public boolean delUseModel(Long qq,Class<?> modelClass){
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("model");
array.remove(modelClass.getName());
json.put("model",array);
return RedisTools.set(qq,json.toJSONString());
}
return false;
}
public boolean isExistsPower(Long qq, String... power){
//1
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("power");
for (String key : power) {
if(!array.contains(key)){
return false;
}
}
return true;
}
return false;
}
public boolean isGroup(Long qq){
if(RedisTools.exists(qq,null)){
JSONObject json= JSON.parseObject(RedisTools.get(qq));
return json.getBooleanValue("group");
}
return false;
}
public boolean isUseModel(Long qq,Class<?> modelClass){
if(RedisTools.exists(qq,null)){
JSONObject json=JSON.parseObject(RedisTools.get(qq));
JSONArray array=json.getJSONArray("model");
return array.contains(modelClass.getName());
}
return false;
}
}

View File

@ -0,0 +1,29 @@
package com.yutou.napcat.enums;
public enum MessageEnum {
TEXT("text"),
IMAGE("image"),
AT("at"),
REPLY("reply"),
JSON("json");
String type;
MessageEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
public static MessageEnum of(String type) {
for (MessageEnum messageEnum : MessageEnum.values()) {
if (messageEnum.getType().equals(type)) {
return messageEnum;
}
}
return null;
}
}

View File

@ -0,0 +1,28 @@
package com.yutou.napcat.enums;
public enum RecordFormatEnum {
MP3("mp3"),
AMR("amr"),
WMA("wma"),
M4A("m4a"),
SPX("spx"),
OGG("ogg"),
WAV("wav"),
FLAC("flac");
private final String format;
RecordFormatEnum(String format) {
this.format = format;
}
public String getFormat() {
return format;
}
@Override
public String toString() {
return format;
}
}

View File

@ -0,0 +1,12 @@
package com.yutou.napcat.event;
import com.yutou.napcat.model.GroupFrom;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class GroupMessageEvent extends MessageEvent {
private GroupFrom group;
}

View File

@ -0,0 +1,183 @@
package com.yutou.napcat.event;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.napcat.QQDatabase;
import com.yutou.napcat.enums.MessageEnum;
import com.yutou.napcat.handle.*;
import com.yutou.napcat.model.SourceFrom;
import lombok.Data;
import lombok.val;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
@Data
public class MessageEvent {
@JSONField(name = "self_id")
private Long selfId;
@JSONField(name = "user_id")
private Long userId;
@JSONField(name = "time")
private Long time;
@JSONField(name = "message_id")
private Integer messageId;
@JSONField(name = "real_id")
private Integer realId;
@JSONField(name = "message_type")
private String messageType;
@JSONField(name = "sender")
private SourceFrom source;
@JSONField(name = "raw_message")
private String rawMessage;
@JSONField(name = "font")
private Integer font;
@JSONField(name = "sub_type")
private String subType;
@JSONField(name = "message")
private List<BaseHandle<?>> message;
@JSONField(name = "message_format")
private String messageFormat;
@JSONField(name = "post_type")
private String postType;
@JSONField(name = "group_id")
private Long groupId;
public static MessageEvent parseHandleHttp(String jsonString) {
return parseHandle(JSONObject.parseObject(jsonString).getJSONObject("data").toString());
}
public static MessageEvent parseHandle(String jsonString) {
JSONObject json = JSONObject.parseObject(jsonString);
JSONArray array = json.getJSONArray("message");
List<BaseHandle<?>> messageList = new ArrayList<>();
for (Object o : array) {
JSONObject _json = (JSONObject) o;
Type classType = null;
MessageEnum _type = MessageEnum.of(_json.getString("type"));
classType = switch (_type) {
case TEXT -> Text.TextInfo.class;
case IMAGE -> Image.ImageInfo.class;
case AT -> At.AtData.class;
case JSON -> OtherHandle.OtherInfo.class;
case REPLY -> Reply.ReplyInfo.class;
default -> classType;
};
BaseHandle<?> handle = new BaseHandle<>(_type.getType());
if (_type == MessageEnum.JSON) {
handle.setData(JSONObject.parseObject(((JSONObject) o).getJSONObject("data").getString("data"), classType));
} else {
handle.setData(JSONObject.parseObject(((JSONObject) o).getJSONObject("data").toString(), classType));
}
messageList.add(handle);
}
SourceFrom sender = new SourceFrom();
sender.setUserId(json.getJSONObject("sender").getLong("user_id"));
sender.setNickname(json.getJSONObject("sender").getString("nickname"));
sender.setCard(json.getJSONObject("sender").getString("card"));
MessageEvent event = new MessageEvent();
event.setSelfId(json.getLong("self_id"));
event.setUserId(json.getLong("user_id"));
event.setTime(json.getLong("time"));
event.setMessageId(json.getInteger("message_id"));
event.setRealId(json.getInteger("real_id"));
event.setMessageType(json.getString("message_type"));
event.setSource(sender);
event.setRawMessage(json.getString("raw_message"));
event.setFont(json.getInteger("font"));
event.setSubType(json.getString("sub_type"));
event.setMessageFormat(json.getString("message_format"));
event.setPostType(json.getString("post_type"));
event.setGroupId(json.getLong("group_id"));
event.setMessage(messageList);
return event;
}
public boolean hasType(MessageEnum messageEnum) {
for (BaseHandle<?> handle : message) {
if (MessageEnum.of(handle.getType()) == messageEnum) {
return true;
}
}
return false;
}
public <T extends BaseHandle> List<T> findAllType(Class<T> t) {
List<T> tmp = new ArrayList<>();
try {
T newed = t.getDeclaredConstructor().newInstance();
for (BaseHandle<?> baseHandle : message) {
if (baseHandle.getType().equals(newed.getType())) {
newed.setData(baseHandle.getData());
tmp.add(newed);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return tmp;
}
public <T extends BaseHandle> T findType(Class<T> tClass) {
List<T> list = findAllType(tClass);
if (list == null || list.isEmpty()) {
return null;
}
return list.get(0);
}
public boolean isAtMe() {
if (!hasType(MessageEnum.AT)) {
return false;
}
List<At> list = findAllType(At.class);
for (At handle : list) {
if (handle.getData().getQq() == QQDatabase.getMe().getUserId()) {
return true;
}
}
return false;
}
public String getTextMessage() {
val texts = findAllType(Text.class);
StringBuilder sb = new StringBuilder();
for (Text text : texts) {
sb.append(text);
}
return sb.toString().trim();
}
public boolean isUser() {
return "private".equals(messageType);
}
public boolean isGroup() {
return "group".equals(messageType);
}
}

View File

@ -0,0 +1,32 @@
package com.yutou.napcat.handle;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
public class At extends BaseHandle<At.AtData> {
public At() {
super("at");
}
public At(Long userId) {
super("at");
data = new AtData(userId);
}
@Override
public String toString() {
if (data == null) {
return null;
}
return String.format("[CQ:at,qq=%d]", data.qq);
}
@Data
public class AtData extends BaseBean {
private Long qq;
public AtData(Long qq) {
this.qq = qq;
}
}
}

View File

@ -0,0 +1,22 @@
package com.yutou.napcat.handle;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
@Data
public class BaseHandle<T> extends BaseBean {
protected String type;
protected T data;
protected String src;
public BaseHandle(String type) {
this.type = type;
}
public BaseHandle(String type, Object obj) {
super();
this.type = type;
this.data= (T) obj;
}
}

View File

@ -0,0 +1,35 @@
package com.yutou.napcat.handle;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.utils.Base64Tools;
import lombok.Data;
import java.io.File;
public class Image extends BaseHandle<Image.ImageInfo> {
public Image() {
super("image");
}
public Image(String imageUrl) {
super("image");
data = new ImageInfo(imageUrl);
}
public Image(File imageFile){
super("image");
data=new ImageInfo("base64://"+ Base64Tools.encode(imageFile));
}
@Data
public static class ImageInfo {
String file;
String url;
@JSONField(name = "file_size")
String fileSize;
public ImageInfo(String file) {
this.file = file;
}
}
}

View File

@ -0,0 +1,53 @@
package com.yutou.napcat.handle;
import com.alibaba.fastjson2.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class MessageHandleBuild {
private List<BaseHandle<?>> msgList = new ArrayList<>();
private long qq;
private boolean autoEscape;
private boolean isGroup;
public static MessageHandleBuild create() {
return new MessageHandleBuild();
}
private MessageHandleBuild() {
msgList = new ArrayList<>();
}
public MessageHandleBuild setQQNumber(long qq) {
this.qq = qq;
return this;
}
public MessageHandleBuild setAutoEscape(boolean autoEscape) {
this.autoEscape = autoEscape;
return this;
}
public MessageHandleBuild add(BaseHandle<?> msg) {
msgList.add(msg);
return this;
}
public MessageHandleBuild setGroup(boolean group) {
isGroup = group;
return this;
}
public JSONObject build() {
JSONObject json=new JSONObject();
if(isGroup){
json.put("group_id", qq);
}else {
json.put("user_id", qq);
}
json.put("auto_escape", autoEscape);
json.put("message", msgList);
return json;
}
}

View File

@ -0,0 +1,19 @@
package com.yutou.napcat.handle;
import com.yutou.napcat.model.AppShareBean;
import lombok.Data;
public class OtherHandle extends BaseHandle<OtherHandle.OtherInfo>{
public OtherHandle() {
super("json");
data= new OtherInfo();
}
@Data
public static class OtherInfo extends AppShareBean{
}
}

View File

@ -0,0 +1,14 @@
package com.yutou.napcat.handle;
public class QuoteReply {
private final String messageId;
public QuoteReply(String messageId) {
this.messageId = messageId;
}
@Override
public String toString() {
return String.format("[CQ:reply,id=%s]",messageId);
}
}

View File

@ -0,0 +1,38 @@
package com.yutou.napcat.handle;
import com.yutou.utils.ConfigTools;
import lombok.Data;
public class Record extends BaseHandle<Record.RecordInfo> {
public Record() {
super("record");
}
public Record(String file) {
super("record");
data = new RecordInfo(file);
}
public Record(String file, boolean proxy) {
super("record");
data = new RecordInfo(file);
data.proxy = proxy ? "1" : "0";
}
@Data
public static class RecordInfo {
String file;
int magic;
String url;
String cache;
String proxy;
String timeout;
public RecordInfo(String file) {
this.file = file;
}
}
}

View File

@ -0,0 +1,24 @@
package com.yutou.napcat.handle;
import lombok.Data;
public class Reply extends BaseHandle<Reply.ReplyInfo> {
public Reply() {
super("reply");
}
public Reply(long id) {
super("reply");
data = new ReplyInfo(id);
}
@Data
public static class ReplyInfo {
private long id;
public ReplyInfo(long id) {
this.id = id;
}
}
}

View File

@ -0,0 +1,51 @@
package com.yutou.napcat.handle;
import lombok.Data;
public class Text extends BaseHandle<Text.TextInfo> {
public Text() {
super("text");
}
public Text(String text) {
super("text");
data = new TextInfo(text + "\n");
}
public Text(String text, boolean isNewLine) {
super("text");
if (isNewLine) {
data = new TextInfo(text + "\n");
} else {
data = new TextInfo(text);
}
}
public Text(boolean isNewLine, String... text) {
super("text");
StringBuilder sb = new StringBuilder();
for (String s : text) {
sb.append(s);
}
if (isNewLine) {
data = new TextInfo(sb + "\n");
} else {
data = new TextInfo(sb.toString());
}
}
@Override
public String toString() {
return data.text.trim();
}
@Data
public static class TextInfo {
String text;
public TextInfo(String text) {
this.text = text.trim();
}
}
}

View File

@ -0,0 +1,14 @@
package com.yutou.napcat.http;
import com.yutou.napcat.model.FriendBean;
import com.yutou.okhttp.HttpBody;
import retrofit2.Call;
import retrofit2.http.POST;
import java.util.List;
public interface FriendApi {
@POST("/get_friend_list")
Call<HttpBody<List<FriendBean>>> getFriendList(
);
}

View File

@ -0,0 +1,70 @@
package com.yutou.napcat.http;
import com.yutou.napcat.model.GroupBean;
import com.yutou.napcat.model.GroupUserBean;
import com.yutou.okhttp.BaseBean;
import com.yutou.okhttp.HttpBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
import java.util.List;
public interface GroupApi {
/**
* 禁言
* @param group 群号
* @param user 用户
* @param duration 禁言时长单位秒
*
*/
@FormUrlEncoded
@POST("/set_group_ban")
Call<HttpBody<BaseBean>> groupBan(
@Field("group_id") long group,
@Field("user_id") long user,
@Field("duration") long duration
);
/**
* 禁言群组全体成员
* @param group 群号
*/
@FormUrlEncoded
@POST("/set_group_whole_ban")
Call<HttpBody<BaseBean>> groupBanAll(
@Field("group_id") long group
);
/**
* 获取群组列表
*/
@POST("/get_group_list")
Call<HttpBody<List<GroupBean>>> getGroupList(
);
/**
* 获取群组信息
*/
@POST("/get_group_info")
Call<HttpBody<GroupBean>> getGroupInfo(
);
/**
* 获取群组成员信息
*/
@POST("/get_group_member_info")
Call<HttpBody<GroupUserBean>> getGroupUserInfo(
);
/**
* 获取群组成员列表
* @param group 群号
*/
@FormUrlEncoded
@POST("/get_group_member_list")
Call<HttpBody<GroupUserBean>> getGroupUserList(
@Field("group_id") long group
);
}

View File

@ -0,0 +1,50 @@
package com.yutou.napcat.http;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.napcat.model.MessageBean;
import com.yutou.napcat.model.SendMessageResponse;
import com.yutou.okhttp.BaseBean;
import com.yutou.okhttp.HttpBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface MessageAPI {
/**
* 发送私聊消息
* @param message {@link com.yutou.napcat.handle.MessageHandleBuild}
* @return 消息id
*/
@POST("/send_private_msg")
Call<HttpBody<SendMessageResponse>> sendPrivateMsg(
@Body
JSONObject message);
/**
* 发送群聊消息
* @param message 消息内容
* @return 消息id
*/
@POST("/send_group_msg")
Call<HttpBody<SendMessageResponse>> sendGroupMsg(
@Body
JSONObject message
);
/**
* 撤回消息
* @param messageId 消息id
*/
@FormUrlEncoded
@POST("/delete_msg")
Call<HttpBody<BaseBean>> delMsg(
@Field("message_id") long messageId
);
@FormUrlEncoded
@POST("/get_msg")
Call<HttpBody<MessageBean>> getMessage(
@Field("message_id") long messageId
);
}

View File

@ -0,0 +1,33 @@
package com.yutou.napcat.http;
import com.yutou.okhttp.HttpLoggingInterceptor;
import com.yutou.okhttp.api.BaseApi;
import com.yutou.utils.ConfigTools;
public class NapCatApi extends BaseApi {
private static final String URL;
static {
URL= ConfigTools.load(ConfigTools.CONFIG,ConfigTools.NAPCAT_URL,String.class);
}
public NapCatApi() {
super(URL);
}
public static void setLog(boolean log){
HttpLoggingInterceptor.setLog(log);
}
public static MessageAPI getMessageApi(){
return new NapCatApi().setURL(URL).createApi(MessageAPI.class);
}
public static UtilsApi getUtilsApi(){
return new NapCatApi().setURL(URL).createApi(UtilsApi.class);
}
public static GroupApi getGroupApi(){
return new NapCatApi().setURL(URL).createApi(GroupApi.class);
}
public static FriendApi getFriendApi(){
return new NapCatApi().setURL(URL).createApi(FriendApi.class);
}
}

View File

@ -0,0 +1,80 @@
package com.yutou.napcat.http;
import com.yutou.napcat.model.*;
import com.yutou.okhttp.BaseBean;
import com.yutou.okhttp.HttpBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface UtilsApi {
/**
* 获取语音
*
* @param fileId 收到的语音文件名消息段的 file 参数 0B38145AA44505000B38145AA4450500.silk
* @param format 要转换到的格式目前支持 mp3amrwmam4aspxoggwavflac {@link com.yutou.napcat.enums.RecordFormatEnum}
* @return 转换后的语音文件路径
*/
@FormUrlEncoded
@POST("/get_record")
Call<HttpBody<String>> getMessageRecord(
@Field("file") String fileId,
@Field("out_format") String format
);
/**
* 获取图片
*
* @param fileId 收到的图片文件名消息段的 file 参数
* @return 下载后的图片文件路径
*/
@FormUrlEncoded
@POST("/get_image")
Call<HttpBody<String>> getMessageImage(
@Field("file") String fileId
);
/**
* 检查是否可以发送图片
*/
@POST("/can_send_image")
Call<HttpBody<CheckSendImageBean>> checkSendImage(
);
/**
* 检查是否可以发送语音
*/
@POST("/can_send_record")
Call<HttpBody<CheckSendRecordBean>> checkSendRecord(
);
/**
* 获取机器人状态
*/
@POST("/get_status")
Call<HttpBody<QQBotStatusBean>> checkQQBotStatus(
);
/**
* 获取机器人版本信息
*/
@POST("/get_version_info")
Call<HttpBody<QQBotVersionBean>> checkQQBotVersion(
);
/**
* 清理缓存
*/
@POST("/clean_cache")
Call<HttpBody<BaseBean>> cleanCache(
);
/**
* 获取登录信息
*/
@POST("/get_login_info")
Call<HttpBody<FriendBean>> getLoginInfo(
);
}

View File

@ -0,0 +1,139 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
import java.util.Map;
@Data
public class AppShareBean extends BaseBean {
@JSONField(name = "ver")
private String version;
@JSONField(name = "prompt")
private String prompt;
@JSONField(name = "config")
private Config config;
@JSONField(name = "needShareCallBack")
private boolean needShareCallBack;
@JSONField(name = "app")
private String app;
@JSONField(name = "view")
private String view;
@JSONField(name = "meta")
private Meta meta;
// getters and setters...
// Inner classes
@Data
public static class Config {
@JSONField(name = "type")
private String type;
@JSONField(name = "width")
private int width;
@JSONField(name = "height")
private int height;
@JSONField(name = "forward")
private int forward;
@JSONField(name = "autoSize")
private int autoSize;
@JSONField(name = "ctime")
private long ctime;
@JSONField(name = "token")
private String token;
// getters and setters...
}
@Data
public static class Meta {
@JSONField(name = "detail_1")
private Detail detail1;
// If there can be multiple "detail_X" entries, you might need a Map
// @JSONField(name = "detail_X")
// private Map<String, Detail> details;
// getters and setters...
}
@Data
public static class Detail {
@JSONField(name = "appid")
private String appid;
@JSONField(name = "appType")
private int appType;
@JSONField(name = "title")
private String title;
@JSONField(name = "desc")
private String desc;
@JSONField(name = "icon")
private String icon;
@JSONField(name = "preview")
private String preview;
@JSONField(name = "url")
private String url;
@JSONField(name = "scene")
private int scene;
@JSONField(name = "host")
private Host host;
@JSONField(name = "shareTemplateId")
private String shareTemplateId;
// Since "shareTemplateData" is an empty object, it can be left as a Map or a specific class
// if you know the structure of the data that might be there
@JSONField(name = "shareTemplateData")
private Map<String, Object> shareTemplateData;
@JSONField(name = "qqdocurl")
private String qqdocurl;
@JSONField(name = "showLittleTail")
private String showLittleTail;
@JSONField(name = "gamePoints")
private String gamePoints;
@JSONField(name = "gamePointsUrl")
private String gamePointsUrl;
// getters and setters...
}
@Data
public static class Host {
@JSONField(name = "uin")
private long uin;
@JSONField(name = "nick")
private String nick;
// getters and setters...
}
}

View File

@ -0,0 +1,12 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
@Data
public class CheckSendImageBean extends BaseBean {
@JSONField(name = "yes")
private boolean yes;
}

View File

@ -0,0 +1,12 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
@Data
public class CheckSendRecordBean extends BaseBean {
@JSONField(name = "yes")
private boolean yes;
}

View File

@ -0,0 +1,15 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
@Data
public class FriendBean extends BaseBean {
@JSONField(name = "user_id")
private long userId;//qq号
@JSONField(name = "nickname")
private String nickName;//昵称
@JSONField(name = "remark")
private String remark;//备注
}

View File

@ -0,0 +1,18 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
@Data
public class GroupBean extends BaseBean {
@JSONField(name = "group_id")
private long groupId;
@JSONField(name = "group_name")
private String groupName;
@JSONField(name = "member_count")
private int userCount;
@JSONField(name = "max_member_count")
private int userMaxCount;
}

View File

@ -0,0 +1,8 @@
package com.yutou.napcat.model;
import lombok.Data;
@Data
public class GroupFrom {
private long id;
}

View File

@ -0,0 +1,69 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
@Data
public class GroupUserBean extends BaseBean {
// 群号
@JSONField(name = "group_id")
private long groupId;
// QQ号
@JSONField(name = "user_id")
private long userId;
// 昵称
@JSONField(name = "nickname")
private String nickname;
// 群名片/备注
@JSONField(name = "card")
private String card;
// 性别male female unknown
@JSONField(name = "sex")
private String sex;
// 年龄
@JSONField(name = "age")
private int age;
// 地区
@JSONField(name = "area")
private String area;
// 加群时间戳
@JSONField(name = "join_time")
private int joinTime;
// 最后发言时间戳
@JSONField(name = "last_sent_time")
private int lastSentTime;
// 成员等级
@JSONField(name = "level")
private String level;
// 角色owner admin member
@JSONField(name = "role")
private String role;
// 是否不良记录成员
@JSONField(name = "unfriendly")
private boolean unfriendly;
// 专属头衔
@JSONField(name = "title")
private String title;
// 专属头衔过期时间戳
@JSONField(name = "title_expire_time")
private int titleExpireTime;
// 是否允许修改群名片
@JSONField(name = "card_changeable")
private boolean cardChangeable;
}

View File

@ -0,0 +1,23 @@
package com.yutou.napcat.model;
import lombok.Data;
@Data
public class Message {
private String message;
private String srcMessage;
private String id;
public Message(String message, String srcMessage) {
this.message = message;
this.srcMessage = srcMessage;
}
public String serializeToMiraiCode(){
return srcMessage;
}
public String contentToString(){
return message;
}
}

View File

@ -0,0 +1,45 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
/**
* 消息
* @see <a href="https://github.com/botuniverse/onebot-11/blob/master/api/public.md#get_msg-%E8%8E%B7%E5%8F%96%E6%B6%88%E6%81%AF">文档</a>
*/
@Data
public class MessageBean extends BaseBean {
/**
*发送时间
*/
@JSONField(name = "time")
private long time;
/**
* 消息类型 <a href="https://github.com/botuniverse/onebot-11/blob/master/event/message.md">消息事件</a>
*/
@JSONField(name = "message_type")
private String type;
/**
* 消息 ID
*/
@JSONField(name = "message_id")
private int messageId;
/**
* 消息真实 ID
*/
@JSONField(name = "real_id")
private int realId;
/**
* 发送人信息 <a href="https://github.com/botuniverse/onebot-11/blob/master/event/message.md">消息事件</a>
*/
@JSONField(name = "sender")
private SenderBean sender;
/**
* 消息内容
*/
@JSONField(name = "message")
private String message;
}

View File

@ -0,0 +1,13 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
@Data
public class QQBotStatusBean extends BaseBean {
@JSONField(name = "online")
private String online;//当前 QQ 在线null 表示无法查询到在线状态
@JSONField(name = "good")
private String good;//状态符合预期意味着各模块正常运行功能正常 QQ 在线
}

View File

@ -0,0 +1,17 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
@Data
public class QQBotVersionBean {
@JSONField(name = "app_name")
private String appName;//应用标识 mirai-native
@JSONField(name = "app_version")
private String appVersion;//应用版本 1.2.3
@JSONField(name = "protocol_version")
private String protocolVersion;//OneBot 标准版本 v11
}

View File

@ -0,0 +1,21 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.google.gson.annotations.SerializedName;
import com.yutou.napcat.handle.BaseHandle;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class SendMessageRequest extends BaseBean {
@JSONField(name = "user_id")
private long userId;
@JSONField
List<BaseHandle<?>> message;
@SerializedName("auto_escape")
private boolean notCQCode;
}

View File

@ -0,0 +1,16 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class SendMessageResponse extends BaseBean {
@JSONField( name = "message_id")
private int id;
private String e;
}

View File

@ -0,0 +1,24 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import com.yutou.okhttp.BaseBean;
import lombok.Data;
/**
* 发送人结构体
*
*/
@Data
public class SenderBean extends BaseBean {
@JSONField(name = "user_id")
private long userId;
@JSONField(name = "nickname")
private String nickName;
/**
* male female unknown
*/
@JSONField(name = "sex")
private String sex;
@JSONField(name = "age")
private int age;
}

View File

@ -0,0 +1,17 @@
package com.yutou.napcat.model;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
@Data
public class SourceFrom {
@JSONField(name = "user_id")
private long userId;
private String nickname;
private String card;
private String role;
public Long getFromId() {
return userId;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}

View File

@ -1,7 +1,5 @@
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;
@ -9,14 +7,13 @@ 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})
@Import({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);
}

View File

@ -1,16 +1,16 @@
package com.yutou.bilibili.Controllers;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.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 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.ResponseBody;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@ -125,8 +125,6 @@ public class SystemConfigController {
@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");

View File

@ -1,29 +1,24 @@
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.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
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 com.yutou.utils.AppTools;
import com.yutou.utils.RedisTools;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
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;
@ -31,8 +26,7 @@ import java.util.UUID;
public class UserController {
@Resource
IUserService service;
@Resource
IBiliBiliLiveService biliService;
@Resource
ISystemConfigService configService;
@ -51,7 +45,7 @@ public class UserController {
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);
RedisTools.set(user.getLogintoken(), user.getId() + "", 30 * 24 * 60);
AppTools.setCookie(response, "login", user.getLogintoken(), -1);
boolean flag = service.reg(user);
if (flag) {
@ -72,7 +66,7 @@ public class UserController {
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);
RedisTools.set(user.getLogintoken(), user.getId() + "", 30 * 24 * 60);
AppTools.setCookie(response, "login", user.getLogintoken(), -1);
json.put("msg", "登陆成功");
json.put("power", user.getPower());
@ -124,7 +118,7 @@ public class UserController {
user.setPower(loginUser.getPower());
user.setBiliCookie(loginUser.getBiliCookie());
user.setSubtime(loginUser.getSubtime());
user.setPassword(AppTools.getMD5 (user.getPassword()));
user.setPassword(AppTools.getMD5(user.getPassword()));
service.update(user);
json.put("code", 0);
json.put("msg", "修改成功");
@ -156,37 +150,6 @@ public class UserController {
@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;
}
@ -199,14 +162,14 @@ public class UserController {
json.put("code", -1);
json.put("msg", "未登录");
} else {
UUser user = service.getUserToUid(Integer.parseInt(RedisTools.get(token)));;
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);
JSONObject ujson = JSONObject.parseObject(JSONObject.toJSONString(user));
ujson.remove("logintoken");
ujson.remove("biliCookie");
ujson.remove("password");

View File

@ -1,449 +1,212 @@
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 com.alibaba.fastjson2.JSONObject;
import com.yutou.napcat.QQDatabase;
import com.yutou.napcat.QQNumberManager;
import com.yutou.napcat.handle.BaseHandle;
import com.yutou.napcat.handle.MessageHandleBuild;
import com.yutou.napcat.handle.Reply;
import com.yutou.napcat.handle.Text;
import com.yutou.napcat.http.NapCatApi;
import com.yutou.napcat.model.FriendBean;
import com.yutou.napcat.model.GroupBean;
import com.yutou.napcat.model.SendMessageResponse;
import com.yutou.okhttp.HttpBody;
import com.yutou.okhttp.HttpCallback;
import com.yutou.utils.ConfigTools;
import okhttp3.Headers;
import retrofit2.Response;
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.Arrays;
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;
public class QQBotManager {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (QQBotManager.applicationContext == null) {
QQBotManager.applicationContext = applicationContext;
}
}
public static Long defGroup = 891655174L;
public static Long defQQ = 583819556L;
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 static final long qqGroup = 891655174L;
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("登陆成功");
Boolean isRun = ConfigTools.load(ConfigTools.CONFIG, "qq_bot", Boolean.class);
if (isRun != null && isRun) {
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();
init();
}
}
public static QQBotManager getInstance() {
private void init() {
NapCatApi.getGroupApi().getGroupList().enqueue(new HttpCallback<List<GroupBean>>() {
@Override
public void onResponse(Headers headers,int code, String status, List<GroupBean> response, String rawResponse) {
for (GroupBean groupBean : response) {
QQDatabase.addGroup(groupBean.getGroupId(), groupBean);
QQNumberManager.getManager().addNumber(groupBean.getGroupId(), true);
}
}
@Override
public void onFailure(Throwable throwable) {
}
});
NapCatApi.getFriendApi().getFriendList().enqueue(new HttpCallback<List<FriendBean>>() {
@Override
public void onResponse(Headers headers,int code, String status, List<FriendBean> response, String rawResponse) {
for (FriendBean friendBean : response) {
QQDatabase.addUser(friendBean.getUserId(), friendBean);
QQNumberManager.getManager().addNumber(friendBean.getUserId(), false);
}
}
@Override
public void onFailure(Throwable throwable) {
}
});
NapCatApi.getUtilsApi().getLoginInfo().enqueue(new HttpCallback<FriendBean>() {
@Override
public void onResponse(Headers headers,int code, String status, FriendBean response, String rawResponse) {
QQDatabase.setMe(response);
}
@Override
public void onFailure(Throwable throwable) {
}
});
isInit = true;
}
public synchronized 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 SendMessageResponse sendPrivateMessage(Long qq, BaseHandle<?>... items) {
return sendMessage(true, qq, items);
}
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();
private SendMessageResponse sendGroupMessage(Long group, BaseHandle<?>... items) {
return sendMessage(false, group, items);
}
public void sendMessage(Long group, MessageChainBuilder builder) {
if (bot != null) {
Objects.requireNonNull(bot.getGroup(group)).sendMessage(builder.asMessageChain());
}
public SendMessageResponse sendMessage(boolean user, Long qq, String msg) {
return sendMessage(user, qq, new Text(msg));
}
public SendMessageResponse sendMessage(Long qq, BaseHandle<?>... items) {
return sendMessage(QQDatabase.checkFriend(qq), qq, Arrays.asList(items));
}
public String sendMessage(File imageFile, String text) {
public SendMessageResponse sendMessage(boolean isUser, Long qq, BaseHandle<?>... items) {
return sendMessage(isUser, qq, Arrays.asList(items));
}
public SendMessageResponse sendMessage(boolean isUser, Long qq, List<BaseHandle<?>> items) {
try {
if (bot != null) {
Image image = getImage(imageFile);
MessageChainBuilder builder = new MessageChainBuilder();
if (image != null) {
builder.append(image);
if(!ConfigTools.load(ConfigTools.CONFIG,ConfigTools.QQ, Boolean.class)){
return null;
}
MessageHandleBuild handleBuild = MessageHandleBuild
.create()
.setGroup(!isUser)
.setQQNumber(qq);
for (BaseHandle<?> item : items) {
if (item.getData() == null) {
continue;
}
builder.append(text);
return Objects.requireNonNull(bot.getGroup(qqGroup)).sendMessage(builder.asMessageChain()).toString();
if (item instanceof Reply) {
if (((Reply) item).getData().getId() == -1) {
continue;
}
}
handleBuild.add(item);
}
Response<HttpBody<SendMessageResponse>> response;
if (isUser) {
response = NapCatApi.getMessageApi().sendPrivateMsg(
handleBuild.build()
).execute();
} else {
response = NapCatApi.getMessageApi().sendGroupMsg(
handleBuild.build()
).execute();
}
if (response.body() != null) {
return response.body().getData();
}
} catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e);
e.printStackTrace();
SendMessageResponse response = new SendMessageResponse();
response.setId(-1);
response.setE(e.getMessage());
return response;
}
return null;
}
public String sendMessage(String text) {
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();
public SendMessageResponse sendMessage(Long group, String text) {
return sendMessage(QQDatabase.checkFriend(group), group, new Text(text));
}
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());
public void sendMessage(Long group, StringBuilder builder) {
if (QQNumberManager.getManager().isGroup(group)) {
System.out.println("发群");
} else {
System.out.println("发个人");
}
return list;
}
public void sendMessage(File imageFile, Long qq, String text) {
sendMessage(imageFile, qq, null, text);
}
public void sendMessage(File imageFile, Long qq, String replyMessageId, String text) {
}
public void sendMessage(File imageFile, String text) {
}
public void sendMessage(List<File> imgs, Long qq, String text) {
}
public static void main(String[] args) {
getInstance();
JSONObject json = new JSONObject();
json.put("t1", 3234567890L);
System.out.println("json = " + json);
String tmp = json.toString();
JSONObject json2 = JSONObject.parseObject(tmp);
System.out.println("json2 = " + json2);
}
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);
}
public boolean isLogin() {
return true;
}
}

View File

@ -4,9 +4,9 @@ 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 jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service("SystemConfigService")

View File

@ -1,20 +1,17 @@
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 com.yutou.utils.AppTools;
import jakarta.annotation.Resource;
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")
@ -26,7 +23,7 @@ public class UserServiceImpl implements IUserService {
@Override
public boolean login(String uname, String password) {
UUserExample example=new UUserExample();
String _password=AppTools.getMD5 (password);
String _password= AppTools.getMD5 (password);
example.createCriteria().andUserEqualTo(uname).andPasswordEqualTo(_password);
return !userDao.selectByExample(example).isEmpty();
}

View File

@ -1,40 +1,8 @@
package com.yutou.bilibili.Test;
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.LiveUtils;
import com.yutou.bilibili.BiliBili.Tools.LiveT;
import com.yutou.bilibili.BiliBili.Tools.SaveLive;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@ResponseBody
@RequestMapping("/add.do")
public String test(int a) {
return "ok";
}
@ResponseBody
@RequestMapping("/get.do")
public JSONObject get(){
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;
}
}

View File

@ -1,20 +1,23 @@
package com.yutou.bilibili.Tools;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.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 com.yutou.utils.AppTools;
import com.yutou.utils.Log;
import com.yutou.utils.RedisTools;
import jakarta.annotation.Resource;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
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;
@ -59,8 +62,8 @@ public class APIFilter implements Filter {
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);
Log.e(e);
Log.i("无权限请求:" + tmp);
return;
}
JSONArray powers = JSONArray.parseArray(user.getPower());

View File

@ -1,5 +1,6 @@
package com.yutou.bilibili.Tools;
import com.yutou.utils.Log;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

View File

@ -2,18 +2,14 @@ package com.yutou.bilibili.Tools;
import com.yutou.bilibili.BiliBili.Datas.AppData;
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.Services.ISystemConfigService;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliLiveInfo;
import com.yutou.bilibili.mybatis.Bili.mybatis.model.BilibiliUpInfo;
import jakarta.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.io.File;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
@ -27,8 +23,6 @@ import java.util.TimerTask;
*/
@Component
public class ApplicationInit implements ApplicationRunner {
@Resource
IBiliBiliLiveService service;
@Resource
ISystemConfigService configService;
private Timer timer;
@ -36,7 +30,6 @@ public class ApplicationInit implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
LiveUtils.LiveGiftConfig.getInstance();
AppData.FFMPEG = configService.getConfig(Config.SYSTEM_VIDEO_FFMPEG);
AppData.LIVE_SAVE_FFMPEG = configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL) != null && configService.getConfig(Config.SYSTEM_VIDEO_SAVE_MODEL).equals("ffmpeg");
startTimer();
@ -59,9 +52,7 @@ public class ApplicationInit implements ApplicationRunner {
oldTime = time;
switch (time) {
case "00:00":
for (Live live : Live.lives.values()) {
live.clearInfo();
}
break;
case "01:00":
case "02:00":
@ -93,52 +84,13 @@ public class ApplicationInit implements ApplicationRunner {
}
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);
}
}
}

View File

@ -4,13 +4,15 @@ 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 com.yutou.utils.AppTools;
import com.yutou.utils.Log;
import jakarta.annotation.Resource;
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;
@ -28,10 +30,10 @@ public class ExcelUtils implements ApplicationContextAware {
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");
Log.i("开始注入bean");
utils.dataDao = getBean(BilibiliLiveDataDao.class);
utils.infoDao = getBean(BilibiliLiveInfoDao.class);
com.yutou.bilibili.Tools.Log.i("注入完毕:"+(System.currentTimeMillis()-timer));
Log.i("注入完毕:"+(System.currentTimeMillis()-timer));
return utils.initTable(roomId, startTime, endTime,fileName);
}
@ -41,7 +43,7 @@ public class ExcelUtils implements ApplicationContextAware {
private File initTable(int roomId, Date startTime, Date endTime,String fileName) {
long timer=System.currentTimeMillis();
com.yutou.bilibili.Tools.Log.i("进入统计:"+timer);
Log.i("进入统计:"+timer);
Workbook workbook = new XSSFWorkbook();
Sheet liveData = workbook.createSheet("直播数据");
Sheet liveInfo = workbook.createSheet("小时统计");
@ -66,7 +68,7 @@ public class ExcelUtils implements ApplicationContextAware {
createCell(infoRow.createCell(5), "送礼人数");
createCell(infoRow.createCell(6), "记录时间");
com.yutou.bilibili.Tools.Log.i("表头插入完毕:"+(System.currentTimeMillis()-timer));
Log.i("表头插入完毕:"+(System.currentTimeMillis()-timer));
List<BilibiliLiveData> dataList = dataDao.queryLiveData(roomId, startTime, endTime, new String[]{
INTERACT_WORD,
ENTRY_EFFECT,
@ -104,7 +106,7 @@ public class ExcelUtils implements ApplicationContextAware {
createCell(infoRow.createCell(5), info.getGiftuser());
createCell(infoRow.createCell(6), AppTools.getToDayTimeToString(info.getSubtime()));
}
com.yutou.bilibili.Tools.Log.i("数据填充完毕:"+(System.currentTimeMillis()-timer));
Log.i("数据填充完毕:"+(System.currentTimeMillis()-timer));
try {
if(!new File("excel").exists()){
new File("excel").mkdirs();
@ -113,11 +115,11 @@ public class ExcelUtils implements ApplicationContextAware {
FileOutputStream fileOutputStream = new FileOutputStream(file);
workbook.write(fileOutputStream);
workbook.close();
com.yutou.bilibili.Tools.Log.i("文件写入完毕:"+(System.currentTimeMillis()-timer));
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);
Log.e(e);
}
return null;

View File

@ -1,5 +1,8 @@
package com.yutou.bilibili.Tools;
import com.yutou.utils.AppTools;
import com.yutou.utils.Log;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
@ -38,8 +41,8 @@ public class FFmpegUtils {
ffmpeg,
file.getAbsolutePath(),
out.getAbsolutePath() + File.separator + file.getName());
com.yutou.bilibili.Tools.Log.i(exec);
Process process=AppTools.exec(exec);
Log.i(exec);
Process process= AppTools.exec(exec);
InputStream inputStream = process.getErrorStream();
byte[] bytes = new byte[1024];
while (inputStream.read(bytes) > -1) {
@ -49,7 +52,7 @@ public class FFmpegUtils {
file.delete();
new File(out.getAbsolutePath()+File.separator+file.getName()).delete();
} catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
}
nowFFmpegList.remove(file);
}
@ -61,13 +64,13 @@ public class FFmpegUtils {
int 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"));
com.yutou.bilibili.Tools.Log.i(i);
Log.i(i);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
}
}
com.yutou.bilibili.Tools.Log.i("转码完成");
Log.i("转码完成");
}
}

View File

@ -1,7 +1,8 @@
package com.yutou.bilibili.Tools;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSONObject;
import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.utils.Log;
import org.springframework.util.StringUtils;
import java.io.*;

View File

@ -1,17 +1,18 @@
package com.yutou.bilibili.Tools;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.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 com.yutou.utils.Log;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
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 {
@ -36,8 +37,8 @@ public class ServiceTools implements ApplicationContextAware {
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);
Log.e(e);
Log.i("无权限请求:" + tmp);
return false;
}
JSONArray powers = JSONArray.parseArray(user.getPower());

View File

@ -1,19 +1,10 @@
package com.yutou.bilibili.Tools;
import com.alibaba.fastjson.JSONObject;
import com.yutou.bilibili.BiliBili.LiveUtils;
import com.alibaba.fastjson2.JSONObject;
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) {
@ -21,43 +12,7 @@ public class 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;
}
}

View File

@ -1,23 +1,18 @@
package com.yutou.bilibili.Tools;
import com.alibaba.fastjson.JSONArray;
import com.yutou.bilibili.interfaces.DownloadInterface;
import com.yutou.utils.Log;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Base64;
@ -111,7 +106,7 @@ public class Tools {
inputStream.close();
downloadInterface.onDownload(file);
} catch (IOException e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
downloadInterface.onError(e);
}
}
@ -153,7 +148,7 @@ public class Tools {
}
in.close();
} catch (Exception e) {
com.yutou.bilibili.Tools.Log.e(e);
Log.e(e);
return null;
}
return bytesToHexString(digest.digest());

View File

@ -4,7 +4,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.yutou.bilibili.BiliBili.LiveUtils;
import lombok.Data;
/**
@ -50,7 +49,6 @@ public class BilibiliUpInfo implements Serializable {
public Integer checkLiveStatus(){
List<BilibiliUpInfo> list=new ArrayList<>();
list.add(this);
live= LiveUtils.getStatusInfoByUid(list).getJSONObject("data").getJSONObject(mid+"").getInteger("live_status");
return live;
}

Some files were not shown because too many files have changed in this diff Show More