新版改版:
模块化各个功能 改为okhttp网络请求 改为sqlite作为存储 预设QQ机器人API
This commit is contained in:
26
biliapi/pom.xml
Normal file
26
biliapi/pom.xml
Normal 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>
|
||||
18
biliapi/src/main/java/com/yutou/bili/api/LoginApi.java
Normal file
18
biliapi/src/main/java/com/yutou/bili/api/LoginApi.java
Normal 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);
|
||||
|
||||
|
||||
}
|
||||
11
biliapi/src/main/java/com/yutou/bili/api/UserApi.java
Normal file
11
biliapi/src/main/java/com/yutou/bili/api/UserApi.java
Normal 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();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.yutou.bili.bean.login;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.yutou.databases.AbsDatabasesBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LoginCookie extends AbsDatabasesBean {
|
||||
@JSONField(name = "SESSDATA")
|
||||
String sessdta;
|
||||
@JSONField(name = "Path")
|
||||
String path;
|
||||
@JSONField(name = "DedeUserID")
|
||||
String dedeUserID;
|
||||
@JSONField(name = "DedeUserID__ckMd5")
|
||||
String dedeUserIDCkMd5;
|
||||
@JSONField(name = "bili_jct")
|
||||
String biliJct;
|
||||
@JSONField(name = "Expires")
|
||||
String expires;
|
||||
@JSONField(name = "Domain")
|
||||
String domain;
|
||||
@JSONField(name = "sid")
|
||||
String sid;
|
||||
@JSONField(name = "gourl")
|
||||
String gourl;
|
||||
|
||||
public LoginCookie() {
|
||||
setTableName("login_cookie");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.yutou.bili.bean.login;
|
||||
|
||||
import com.yutou.okhttp.BaseBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class LoginInfoBean extends BaseBean {
|
||||
private String url;
|
||||
private String refresh_token;
|
||||
private long timestamp;
|
||||
private int code;
|
||||
private String message;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.yutou.bili.bean.login;
|
||||
|
||||
|
||||
import com.yutou.okhttp.BaseBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class QRCodeGenerateBean extends BaseBean {
|
||||
|
||||
private String url;
|
||||
private String qrcode_key;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package com.yutou.bili.bean.login;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.yutou.okhttp.BaseBean;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class UserInfoBean extends BaseBean {
|
||||
|
||||
@JSONField(name = "isLogin")
|
||||
private boolean isLogin;
|
||||
|
||||
@JSONField(name = "email_verified")
|
||||
private int emailVerified;
|
||||
|
||||
@JSONField(name = "face")
|
||||
private String face;
|
||||
|
||||
@JSONField(name = "face_nft")
|
||||
private int faceNft;
|
||||
|
||||
@JSONField(name = "face_nft_type")
|
||||
private int faceNftType;
|
||||
|
||||
@JSONField(name = "level_info")
|
||||
private LevelInfo levelInfo;
|
||||
|
||||
@JSONField(name = "mid")
|
||||
private long mid;
|
||||
|
||||
@JSONField(name = "mobile_verified")
|
||||
private int mobileVerified;
|
||||
|
||||
@JSONField(name = "money")
|
||||
private double money;
|
||||
|
||||
@JSONField(name = "moral")
|
||||
private int moral;
|
||||
|
||||
@JSONField(name = "official")
|
||||
private Official official;
|
||||
|
||||
@JSONField(name = "officialVerify")
|
||||
private OfficialVerify officialVerify;
|
||||
|
||||
@JSONField(name = "pendant")
|
||||
private Pendant pendant;
|
||||
|
||||
@JSONField(name = "scores")
|
||||
private int scores;
|
||||
|
||||
@JSONField(name = "uname")
|
||||
private String uname;
|
||||
|
||||
@JSONField(name = "vipDueDate")
|
||||
private Date vipDueDate;
|
||||
|
||||
@JSONField(name = "vipStatus")
|
||||
private int vipStatus;
|
||||
|
||||
@JSONField(name = "vipType")
|
||||
private int vipType;
|
||||
|
||||
@JSONField(name = "vip_pay_type")
|
||||
private int vipPayType;
|
||||
|
||||
@JSONField(name = "vip_theme_type")
|
||||
private int vipThemeType;
|
||||
|
||||
@JSONField(name = "vip_label")
|
||||
private VipLabel vipLabel;
|
||||
|
||||
@JSONField(name = "vip_avatar_subscript")
|
||||
private int vipAvatarSubscript;
|
||||
|
||||
@JSONField(name = "vip_nickname_color")
|
||||
private String vipNicknameColor;
|
||||
|
||||
@JSONField(name = "vip")
|
||||
private Vip vip;
|
||||
|
||||
@JSONField(name = "wallet")
|
||||
private Wallet wallet;
|
||||
|
||||
@JSONField(name = "has_shop")
|
||||
private boolean hasShop;
|
||||
|
||||
@JSONField(name = "shop_url")
|
||||
private String shopUrl;
|
||||
|
||||
@JSONField(name = "allowance_count")
|
||||
private int allowanceCount;
|
||||
|
||||
@JSONField(name = "answer_status")
|
||||
private int answerStatus;
|
||||
|
||||
@JSONField(name = "is_senior_member")
|
||||
private boolean isSeniorMember;
|
||||
|
||||
@JSONField(name = "wbi_img")
|
||||
private WbiImg wbiImg;
|
||||
|
||||
@JSONField(name = "is_jury")
|
||||
private boolean isJury;
|
||||
|
||||
// 省略了getters和setters
|
||||
|
||||
// level_info的内部数据结构
|
||||
@Data
|
||||
public static class LevelInfo {
|
||||
@JSONField(name = "current_level")
|
||||
private int currentLevel;
|
||||
|
||||
@JSONField(name = "current_min")
|
||||
private int currentMin;
|
||||
|
||||
@JSONField(name = "current_exp")
|
||||
private int currentExp;
|
||||
|
||||
@JSONField(name = "next_exp")
|
||||
private String nextExp;
|
||||
|
||||
// getters and setters
|
||||
}
|
||||
|
||||
// official的结构
|
||||
@Data
|
||||
public static class Official {
|
||||
@JSONField(name = "role")
|
||||
private int role;
|
||||
|
||||
@JSONField(name = "title")
|
||||
private String title;
|
||||
|
||||
@JSONField(name = "desc")
|
||||
private String desc;
|
||||
|
||||
@JSONField(name = "type")
|
||||
private int type;
|
||||
|
||||
// getters and setters
|
||||
}
|
||||
|
||||
// officialVerify的结构
|
||||
@Data
|
||||
public static class OfficialVerify {
|
||||
@JSONField(name = "type")
|
||||
private int type;
|
||||
|
||||
@JSONField(name = "desc")
|
||||
private String desc;
|
||||
|
||||
// getters and setters
|
||||
}
|
||||
|
||||
// pendant的结构
|
||||
@Data
|
||||
public static class Pendant {
|
||||
@JSONField(name = "pid")
|
||||
private int pid;
|
||||
|
||||
@JSONField(name = "name")
|
||||
private String name;
|
||||
|
||||
@JSONField(name = "image")
|
||||
private String image;
|
||||
|
||||
@JSONField(name = "expire")
|
||||
private int expire;
|
||||
|
||||
@JSONField(name = "image_enhance")
|
||||
private String imageEnhance;
|
||||
|
||||
@JSONField(name = "image_enhance_frame")
|
||||
private String imageEnhanceFrame;
|
||||
|
||||
@JSONField(name = "n_pid")
|
||||
private int nPid;
|
||||
|
||||
// getters and setters
|
||||
}
|
||||
|
||||
// vipLabel的结构
|
||||
@Data
|
||||
public static class VipLabel {
|
||||
@JSONField(name = "path")
|
||||
private String path;
|
||||
|
||||
@JSONField(name = "text")
|
||||
private String text;
|
||||
|
||||
@JSONField(name = "label_theme")
|
||||
private String labelTheme;
|
||||
|
||||
@JSONField(name = "text_color")
|
||||
private String textColor;
|
||||
|
||||
@JSONField(name = "bg_style")
|
||||
private String bgStyle;
|
||||
|
||||
@JSONField(name = "bg_color")
|
||||
private String bgColor;
|
||||
|
||||
@JSONField(name = "border_color")
|
||||
private String borderColor;
|
||||
|
||||
@JSONField(name = "use_img_label")
|
||||
private boolean useImgLabel;
|
||||
|
||||
@JSONField(name = "img_label_uri_hans")
|
||||
private String imgLabelUriHans;
|
||||
|
||||
@JSONField(name = "img_label_uri_hant")
|
||||
private String imgLabelUriHant;
|
||||
|
||||
@JSONField(name = "img_label_uri_hans_static")
|
||||
private String imgLabelUriHansStatic;
|
||||
|
||||
@JSONField(name = "img_label_uri_hant_static")
|
||||
private String imgLabelUriHantStatic;
|
||||
|
||||
// getters and setters
|
||||
}
|
||||
|
||||
// vip的结构,和vipLabel类似
|
||||
@Data
|
||||
public static class Vip {
|
||||
@JSONField(name = "type")
|
||||
private int type;
|
||||
|
||||
@JSONField(name = "status")
|
||||
private int status;
|
||||
|
||||
@JSONField(name = "due_date")
|
||||
private Date dueDate;
|
||||
|
||||
@JSONField(name = "vip_pay_type")
|
||||
private int vipPayType;
|
||||
|
||||
@JSONField(name = "theme_type")
|
||||
private int themeType;
|
||||
|
||||
@JSONField(name = "label")
|
||||
private VipLabel label;
|
||||
|
||||
@JSONField(name = "avatar_subscript")
|
||||
private int avatarSubscript;
|
||||
|
||||
@JSONField(name = "nickname_color")
|
||||
private String nicknameColor;
|
||||
// getters and setters
|
||||
}
|
||||
|
||||
// wallet的结构
|
||||
@Data
|
||||
public static class Wallet {
|
||||
@JSONField(name = "mid")
|
||||
private long mid;
|
||||
|
||||
@JSONField(name = "bcoin_balance")
|
||||
private int bcoinBalance;
|
||||
|
||||
@JSONField(name = "coupon_balance")
|
||||
private int couponBalance;
|
||||
|
||||
@JSONField(name = "coupon_due_time")
|
||||
private int couponDueTime;
|
||||
// getters and setters
|
||||
}
|
||||
|
||||
// WbiImg的结构
|
||||
@Data
|
||||
public static class WbiImg {
|
||||
@JSONField(name = "img_url")
|
||||
private String imgUrl;
|
||||
|
||||
@JSONField(name = "sub_url")
|
||||
private String subUrl;
|
||||
|
||||
// getters and setters
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,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();
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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, "未登录");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user