完成一个 Web API(发送直播间心跳包)

This commit is contained in:
czp 2018-03-02 17:44:40 +08:00
parent 36848182f2
commit a0e19cbb42
9 changed files with 237 additions and 6 deletions

View File

@ -3,7 +3,7 @@
由于B站即使更新客户端, 也会继续兼容以前的旧版本客户端, 所以短期内不用担心 API 失效的问题.
对于一些 Bilibili Android APP 上没有的功能, 可以先[将 token 转换为 cookie](#SSO), 然后再去调用 Bilibili Web API.
对于一些 Bilibili Android APP 上没有的功能, 可以先[将 token 转换为 cookie](#sso), 然后再去调用 Bilibili Web API.
# API 不完全
由于本项目还在开发初期, 大量 API 没有完成, 所以很可能没有你想要的 API.

View File

@ -11,9 +11,9 @@ import com.hiczp.bilibili.api.passport.entity.LoginResponseEntity;
import com.hiczp.bilibili.api.passport.entity.LogoutResponseEntity;
import com.hiczp.bilibili.api.passport.entity.RefreshTokenResponseEntity;
import com.hiczp.bilibili.api.passport.exception.CaptchaMismatchException;
import com.hiczp.bilibili.api.provider.BilibiliCaptchaProvider;
import com.hiczp.bilibili.api.provider.BilibiliServiceProvider;
import com.hiczp.bilibili.api.provider.BilibiliSsoProvider;
import com.hiczp.bilibili.api.provider.*;
import com.hiczp.bilibili.api.web.BilibiliWebAPI;
import com.hiczp.bilibili.api.web.BrowserProperties;
import com.hiczp.bilibili.api.web.cookie.SimpleCookieJar;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
@ -33,7 +33,7 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
public class BilibiliAPI implements BilibiliServiceProvider, BilibiliCaptchaProvider, BilibiliSsoProvider, LiveClientProvider {
public class BilibiliAPI implements BilibiliServiceProvider, BilibiliCaptchaProvider, BilibiliSsoProvider, BilibiliWebAPIProvider, LiveClientProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(BilibiliAPI.class);
private final Long apiInitTime = Instant.now().getEpochSecond(); //记录当前类被实例化的时间
@ -250,6 +250,15 @@ public class BilibiliAPI implements BilibiliServiceProvider, BilibiliCaptchaProv
return simpleCookieJar.getCookiesMap();
}
@Override
public BilibiliWebAPI getBilibiliWebAPI() throws IOException {
return new BilibiliWebAPI(toCookies());
}
public BilibiliWebAPI getBilibiliWebAPI(BrowserProperties browserProperties) throws IOException {
return new BilibiliWebAPI(browserProperties, toCookies());
}
public LoginResponseEntity login(@Nonnull String username, @Nonnull String password) throws IOException, LoginException, CaptchaMismatchException {
return login(username, password, null, null);
}

View File

@ -0,0 +1,9 @@
package com.hiczp.bilibili.api.provider;
import com.hiczp.bilibili.api.web.BilibiliWebAPI;
import java.io.IOException;
public interface BilibiliWebAPIProvider {
BilibiliWebAPI getBilibiliWebAPI() throws IOException;
}

View File

@ -1,4 +1,4 @@
package com.hiczp.bilibili.api;
package com.hiczp.bilibili.api.provider;
import com.hiczp.bilibili.api.live.socket.LiveClient;

View File

@ -0,0 +1,74 @@
package com.hiczp.bilibili.api.web;
import com.hiczp.bilibili.api.BaseUrlDefinition;
import com.hiczp.bilibili.api.interceptor.AddFixedHeadersInterceptor;
import com.hiczp.bilibili.api.web.cookie.SimpleCookieJar;
import com.hiczp.bilibili.api.web.live.LiveService;
import okhttp3.Cookie;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class BilibiliWebAPI {
private final BrowserProperties browserProperties;
private final SimpleCookieJar simpleCookieJar;
private LiveService liveService;
public BilibiliWebAPI(BrowserProperties browserProperties, SimpleCookieJar simpleCookieJar) {
this.browserProperties = browserProperties;
this.simpleCookieJar = simpleCookieJar;
}
public BilibiliWebAPI(SimpleCookieJar simpleCookieJar) {
this(BrowserProperties.defaultSetting(), simpleCookieJar);
}
public BilibiliWebAPI(BrowserProperties browserProperties, Map<String, List<Cookie>> cookiesMap) {
this(browserProperties, new SimpleCookieJar(cookiesMap));
}
public BilibiliWebAPI(Map<String, List<Cookie>> cookiesMap) {
this(BrowserProperties.defaultSetting(), new SimpleCookieJar(cookiesMap));
}
public LiveService getLiveService() {
if (liveService == null) {
liveService = getLiveService(Collections.emptyList(), HttpLoggingInterceptor.Level.BASIC);
}
return liveService;
}
public LiveService getLiveService(@Nonnull List<Interceptor> interceptors, @Nonnull HttpLoggingInterceptor.Level logLevel) {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder
.cookieJar(simpleCookieJar)
.addInterceptor(new AddFixedHeadersInterceptor(
"User-Agent", browserProperties.getUserAgent()
));
interceptors.forEach(okHttpClientBuilder::addInterceptor);
okHttpClientBuilder
.addNetworkInterceptor(new HttpLoggingInterceptor().setLevel(logLevel));
return new Retrofit.Builder()
.baseUrl(BaseUrlDefinition.LIVE)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClientBuilder.build())
.build()
.create(LiveService.class);
}
public SimpleCookieJar getSimpleCookieJar() {
return simpleCookieJar;
}
}

View File

@ -0,0 +1,22 @@
package com.hiczp.bilibili.api.web;
public class BrowserProperties {
private String userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36";
private BrowserProperties() {
}
public static BrowserProperties defaultSetting() {
return new BrowserProperties();
}
public String getUserAgent() {
return userAgent;
}
public BrowserProperties setUserAgent(String userAgent) {
this.userAgent = userAgent;
return this;
}
}

View File

@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class SimpleCookieJar implements CookieJar {
private Map<String, List<Cookie>> cookiesMap;
@ -61,6 +62,12 @@ public class SimpleCookieJar implements CookieJar {
return cookieList;
}
public String getCookiesStringForHost(String host) {
return getCookiesForHost(host).stream()
.map(cookie -> String.format("%s=%s", cookie.name(), cookie.value()))
.collect(Collectors.joining(";"));
}
public Map<String, List<Cookie>> getCookiesMap() {
return cookiesMap;
}

View File

@ -0,0 +1,18 @@
package com.hiczp.bilibili.api.web.live;
import com.hiczp.bilibili.api.web.live.entity.SendHeartBeatResponseEntity;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface LiveService {
//直播间心跳包
//参数为时间戳(不是 unix 时间戳)
//未登录时返回 401
@GET("feed/v1/feed/heartBeat")
Call<SendHeartBeatResponseEntity> sendHeartBeat(@Query("_") long timestamp);
default Call<SendHeartBeatResponseEntity> sendHeartBeat() {
return sendHeartBeat(System.currentTimeMillis());
}
}

View File

@ -0,0 +1,92 @@
package com.hiczp.bilibili.api.web.live.entity;
import com.google.gson.annotations.SerializedName;
public class SendHeartBeatResponseEntity {
/**
* code : 0
* msg : success
* message : success
* data : {"open":1,"has_new":0,"count":0}
*/
@SerializedName("code")
private int code;
@SerializedName("msg")
private String msg;
@SerializedName("message")
private String message;
@SerializedName("data")
private Data data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public static class Data {
/**
* open : 1
* has_new : 0
* count : 0
*/
@SerializedName("open")
private int open;
@SerializedName("has_new")
private int hasNew;
@SerializedName("count")
private int count;
public int getOpen() {
return open;
}
public void setOpen(int open) {
this.open = open;
}
public int getHasNew() {
return hasNew;
}
public void setHasNew(int hasNew) {
this.hasNew = hasNew;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
}