From 650e093dd02264229b748b7ecc0dbbcde764fc4b Mon Sep 17 00:00:00 2001 From: FongMi Date: Fri, 7 Jul 2023 17:27:51 +0800 Subject: [PATCH] Update bilibili by use gson --- app/build.gradle | 1 - .../java/com/github/catvod/bean/Class.java | 2 +- .../java/com/github/catvod/bean/Result.java | 8 +- .../com/github/catvod/bean/bili/Dash.java | 131 ++++++ .../com/github/catvod/bean/bili/Resp.java | 167 +++++++ .../com/github/catvod/demo/MainActivity.java | 4 + .../java/com/github/catvod/spider/Bili.java | 416 +++++------------- 7 files changed, 428 insertions(+), 301 deletions(-) create mode 100644 app/src/main/java/com/github/catvod/bean/bili/Dash.java create mode 100644 app/src/main/java/com/github/catvod/bean/bili/Resp.java diff --git a/app/build.gradle b/app/build.gradle index e0b60279..5e07de9c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,6 +44,5 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.6' implementation 'cn.wanghaomiao:JsoupXpath:2.5.1' implementation 'com.google.zxing:core:3.3.0' - //implementation 'com.orhanobut:logger:2.2.0' implementation 'org.jsoup:jsoup:1.15.3' } \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/bean/Class.java b/app/src/main/java/com/github/catvod/bean/Class.java index cbb3417a..34cfd66c 100644 --- a/app/src/main/java/com/github/catvod/bean/Class.java +++ b/app/src/main/java/com/github/catvod/bean/Class.java @@ -26,7 +26,7 @@ public class Class { } public Class(String typeId, String typeName) { - this(typeId, typeName, ""); + this(typeId, typeName, null); } public Class(String typeId, String typeName, String typeFlag) { diff --git a/app/src/main/java/com/github/catvod/bean/Result.java b/app/src/main/java/com/github/catvod/bean/Result.java index 796c36ed..6954f6b3 100644 --- a/app/src/main/java/com/github/catvod/bean/Result.java +++ b/app/src/main/java/com/github/catvod/bean/Result.java @@ -34,13 +34,13 @@ public class Result { @SerializedName("jx") private int jx; @SerializedName("page") - private int page; + private Integer page; @SerializedName("pagecount") - private int pagecount; + private Integer pagecount; @SerializedName("limit") - private int limit; + private Integer limit; @SerializedName("total") - private int total; + private Integer total; public static Result objectFrom(String str) { return new Gson().fromJson(str, Result.class); diff --git a/app/src/main/java/com/github/catvod/bean/bili/Dash.java b/app/src/main/java/com/github/catvod/bean/bili/Dash.java new file mode 100644 index 00000000..fd81f076 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/bili/Dash.java @@ -0,0 +1,131 @@ +package com.github.catvod.bean.bili; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.util.Collections; +import java.util.List; + +public class Dash { + + @SerializedName("duration") + private String duration; + @SerializedName("minBufferTime") + private String minBufferTime; + @SerializedName("video") + private List video; + @SerializedName("audio") + private List audio; + + public static Dash objectFrom(String str) { + return new Gson().fromJson(str, Dash.class); + } + + public String getDuration() { + return duration == null ? "0" : duration; + } + + public String getMinBufferTime() { + return minBufferTime == null ? "0" : minBufferTime; + } + + public List getVideo() { + return video == null ? Collections.emptyList() : video; + } + + public List getAudio() { + return audio == null ? Collections.emptyList() : audio; + } + + public static class Media { + + @SerializedName("id") + private String id; + @SerializedName("baseUrl") + private String baseUrl; + @SerializedName("bandwidth") + private String bandwidth; + @SerializedName("mimeType") + private String mimeType; + @SerializedName("codecs") + private String codecs; + @SerializedName("width") + private String width; + @SerializedName("height") + private String height; + @SerializedName("frameRate") + private String frameRate; + @SerializedName("sar") + private String sar; + @SerializedName("startWithSap") + private String startWithSap; + @SerializedName("SegmentBase") + private SegmentBase segmentBase; + @SerializedName("codecid") + private String codecid; + + public String getId() { + return id; + } + + public String getBaseUrl() { + return baseUrl; + } + + public String getBandWidth() { + return bandwidth; + } + + public String getMimeType() { + return mimeType; + } + + public String getCodecs() { + return codecs; + } + + public String getWidth() { + return width; + } + + public String getHeight() { + return height; + } + + public String getFrameRate() { + return frameRate; + } + + public String getSar() { + return sar; + } + + public String getStartWithSap() { + return startWithSap; + } + + public SegmentBase getSegmentBase() { + return segmentBase; + } + + public String getCodecId() { + return codecid; + } + } + + public static class SegmentBase { + + @SerializedName("Initialization") + private String initialization; + @SerializedName("indexRange") + private String indexRange; + + public String getInitialization() { + return initialization; + } + + public String getIndexRange() { + return indexRange; + } + } +} diff --git a/app/src/main/java/com/github/catvod/bean/bili/Resp.java b/app/src/main/java/com/github/catvod/bean/bili/Resp.java new file mode 100644 index 00000000..5452c141 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/bili/Resp.java @@ -0,0 +1,167 @@ +package com.github.catvod.bean.bili; + +import android.text.TextUtils; + +import com.github.catvod.bean.Vod; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +import org.jsoup.Jsoup; + +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.List; + +public class Resp { + + @SerializedName("code") + private Integer code; + @SerializedName("message") + private String message; + @SerializedName("data") + private Data data; + + public static Resp objectFrom(String str) { + return new Gson().fromJson(str, Resp.class); + } + + public Data getData() { + return data == null ? new Data() : data; + } + + public static class Data { + + @SerializedName("result") + private JsonElement result; + @SerializedName("aid") + private String aid; + @SerializedName("cid") + private String cid; + @SerializedName("title") + private String title; + @SerializedName("tname") + private String tname; + @SerializedName("pic") + private String pic; + @SerializedName("duration") + private Long duration; + @SerializedName("desc") + private String desc; + @SerializedName("accept_description") + private List acceptDescription; + @SerializedName("accept_quality") + private List acceptQuality; + @SerializedName("pages") + private List pages; + @SerializedName("dash") + private Dash dash; + + public JsonElement getResult() { + return result; + } + + public String getAid() { + return TextUtils.isEmpty(aid) ? "" : aid; + } + + public String getCid() { + return TextUtils.isEmpty(cid) ? "" : cid; + } + + public String getTitle() { + return TextUtils.isEmpty(title) ? "" : title; + } + + public String getType() { + return TextUtils.isEmpty(tname) ? "" : tname; + } + + public String getPic() { + return TextUtils.isEmpty(pic) ? "" : pic; + } + + public Long getDuration() { + return duration == null ? 0 : duration; + } + + public String getDesc() { + return TextUtils.isEmpty(desc) ? "" : desc; + } + + public List getAcceptDescription() { + return acceptDescription == null ? Collections.emptyList() : acceptDescription; + } + + public List getAcceptQuality() { + return acceptQuality == null ? Collections.emptyList() : acceptQuality; + } + + public List getPages() { + return pages == null ? Collections.emptyList() : pages; + } + + public Dash getDash() { + return dash == null ? new Dash() : dash; + } + } + + public static class Page { + + @SerializedName("cid") + private String cid; + @SerializedName("part") + private String part; + + public String getCid() { + return TextUtils.isEmpty(cid) ? "" : cid; + } + + public String getPart() { + return TextUtils.isEmpty(part) ? "" : part; + } + } + + public static class Result { + + @SerializedName("bvid") + private String bvid; + @SerializedName("title") + private String title; + @SerializedName("pic") + private String pic; + @SerializedName("duration") + private String duration; + + public static List arrayFrom(JsonElement str) { + Type listType = new TypeToken>() {}.getType(); + return new Gson().fromJson(str, listType); + } + + public String getBvId() { + return TextUtils.isEmpty(bvid) ? "" : bvid; + } + + public String getTitle() { + return TextUtils.isEmpty(title) ? "" : title; + } + + public String getDuration() { + return TextUtils.isEmpty(duration) ? "" : duration; + } + + public String getPic() { + return TextUtils.isEmpty(pic) ? "" : pic; + } + + public Vod getVod() { + Vod vod = new Vod(); + vod.setVodId(getBvId()); + vod.setVodName(Jsoup.parse(getTitle()).text()); + vod.setVodRemarks(getDuration().split(":")[0] + "分鐘"); + vod.setVodPic(getPic().startsWith("//") ? "https:" + getPic() : getPic()); + return vod; + } + } +} diff --git a/app/src/main/java/com/github/catvod/demo/MainActivity.java b/app/src/main/java/com/github/catvod/demo/MainActivity.java index 87ced705..80e5f8cd 100644 --- a/app/src/main/java/com/github/catvod/demo/MainActivity.java +++ b/app/src/main/java/com/github/catvod/demo/MainActivity.java @@ -15,7 +15,11 @@ public class MainActivity extends Activity { //Logger.addLogAdapter(new AndroidLogAdapter()); Init.init(getApplicationContext()); new Thread(() -> { + try { + } catch (Exception e) { + e.printStackTrace(); + } }).start(); } } \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/spider/Bili.java b/app/src/main/java/com/github/catvod/spider/Bili.java index 565cb062..1e980c5e 100644 --- a/app/src/main/java/com/github/catvod/spider/Bili.java +++ b/app/src/main/java/com/github/catvod/spider/Bili.java @@ -1,100 +1,65 @@ package com.github.catvod.spider; -import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.net.Uri; import android.text.TextUtils; import android.util.Base64; -import android.view.Gravity; -import android.widget.FrameLayout; -import android.widget.ImageView; import com.github.catvod.bean.Class; +import com.github.catvod.bean.Filter; import com.github.catvod.bean.Result; import com.github.catvod.bean.Vod; +import com.github.catvod.bean.bili.Dash; +import com.github.catvod.bean.bili.Resp; import com.github.catvod.crawler.Spider; import com.github.catvod.net.OkHttp; -import com.github.catvod.utils.Prefers; -import com.github.catvod.utils.QRCode; import com.github.catvod.utils.Utils; -import org.json.JSONArray; -import org.json.JSONObject; -import org.jsoup.Jsoup; - import java.net.URLEncoder; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.Locale; +import java.util.Map; /** * @author ColaMint & FongMi & 唐三 */ public class Bili extends Spider { - private ScheduledExecutorService service; - private HashMap header; - private static JSONObject vod_audio_id = new JSONObject(); - private AlertDialog dialog; - private JSONObject ext; + private static final String COOKIE = "buvid3=84B0395D-C9F2-C490-E92E-A09AB48FE26E71636infoc"; + private Map header; + private Map audios; private String extend; - private boolean login; - private static int vip = 0; - - private String getCookie() { - String cache = Prefers.getString("BiliCookie"); - if (!TextUtils.isEmpty(cache)) return cache; - if (ext.optString("cookie").startsWith("http")) - return OkHttp.string(ext.optString("cookie")).replace("\n", "").trim(); - return ext.optString("cookie", "buvid3=84B0395D-C9F2-C490-E92E-A09AB48FE26E71636infoc"); - } private void setHeader() { - header.put("cookie", getCookie()); + header = new HashMap<>(); + header.put("cookie", COOKIE); header.put("Referer", "https://www.bilibili.com"); header.put("User-Agent", Utils.CHROME); } - private void generate() throws Exception { - ext = new JSONObject(); - JSONArray classes = new JSONArray(); - JSONObject filters = new JSONObject(); - ext.put("classes", classes); - ext.put("filter", filters); - JSONArray filter = new JSONArray("[{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"综合排序\",\"v\":\"0\"},{\"n\":\"最多点击\",\"v\":\"click\"},{\"n\":\"最新发布\",\"v\":\"pubdate\"},{\"n\":\"最多弹幕\",\"v\":\"dm\"},{\"n\":\"最多收藏\",\"v\":\"stow\"}]},{\"key\":\"duration\",\"name\":\"时长\",\"value\":[{\"n\":\"全部时长\",\"v\":\"0\"},{\"n\":\"60分钟以上\",\"v\":\"4\"},{\"n\":\"30~60分钟\",\"v\":\"3\"},{\"n\":\"10~30分钟\",\"v\":\"2\"},{\"n\":\"10分钟以下\",\"v\":\"1\"}]}]"); - String[] types = extend.split("#"); - for (String type : types) { - JSONObject c = new JSONObject(); - c.put("type_name", type); - c.put("type_id", type); - filters.put(type, filter); - classes.put(c); - } + private void setAudio() { + audios = new HashMap<>(); + audios.put("30280", "192000"); + audios.put("30232", "132000"); + audios.put("30216", "64000"); } - private void fetchRule() throws Exception { - if (header.containsKey("cookie") && header.get("cookie").length() > 0) return; - if (extend.startsWith("http")) ext = new JSONObject(extend = OkHttp.string(extend)); - else generate(); - setHeader(); + private List getFilter() { + List items = new ArrayList<>(); + items.add(new Filter("order", "排序", Arrays.asList(new Filter.Value("預設", "totalrank"), new Filter.Value("最多點擊", "click"), new Filter.Value("最新發布", "pubdate"), new Filter.Value("最多彈幕", "dm"), new Filter.Value("最多收藏", "stow")))); + items.add(new Filter("duration", "時長", Arrays.asList(new Filter.Value("全部時長", "0"), new Filter.Value("60分鐘以上", "4"), new Filter.Value("30~60分鐘", "3"), new Filter.Value("10~30分鐘", "2"), new Filter.Value("10分鐘以下", "1")))); + return items; } @Override public void init(Context context, String extend) { try { this.extend = extend; - this.header = new HashMap<>(); - fetchRule(); - vod_audio_id.put("30280", "192000"); - vod_audio_id.put("30232", "132000"); - vod_audio_id.put("30216", "64000"); + setHeader(); + setAudio(); } catch (Exception e) { e.printStackTrace(); } @@ -102,115 +67,64 @@ public class Bili extends Spider { @Override public String homeContent(boolean filter) throws Exception { - fetchRule(); - return Result.string(Class.arrayFrom(ext.getJSONArray("classes").toString()), ext.getJSONObject("filter")); + List classes = new ArrayList<>(); + LinkedHashMap> filters = new LinkedHashMap<>(); + String[] types = extend.split("#"); + for (String type : types) { + classes.add(new Class(type)); + filters.put(type, getFilter()); + } + return Result.string(classes, filters); } @Override public String homeVideoContent() throws Exception { - fetchRule(); - return categoryContent(ext.optJSONArray("classes").optJSONObject(0).optString("type_id"), "1", true, new HashMap<>()); + return categoryContent(extend.split("#")[0], "1", true, new HashMap<>()); } @Override public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception { - String duration = extend.containsKey("duration") ? extend.get("duration") : "4"; - if (extend.containsKey("tid")) tid = tid + " " + extend.get("tid"); - String url = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword=" + URLEncoder.encode(tid) + "&duration=" + duration + "&page=" + pg; - JSONObject resp = new JSONObject(OkHttp.string(url, header)); - JSONArray result = resp.getJSONObject("data").getJSONArray("result"); + String order = extend.containsKey("order") ? extend.get("order") : "totalrank"; + String duration = extend.containsKey("duration") ? extend.get("duration") : "0"; + String api = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword=" + URLEncoder.encode(tid) + "&order=" + order + "&duration=" + duration + "&page=" + pg; + String json = OkHttp.string(api, header); + Resp resp = Resp.objectFrom(json); List list = new ArrayList<>(); - for (int i = 0; i < result.length(); ++i) { - JSONObject object = result.getJSONObject(i); - String pic = object.getString("pic"); - Vod vod = new Vod(); - vod.setVodId(object.getString("bvid")); - vod.setVodName(Jsoup.parse(object.getString("title")).text()); - vod.setVodRemarks(object.getString("duration").split(":")[0] + "分鐘"); - vod.setVodPic(pic.startsWith("//") ? "https:" + pic : pic); - list.add(vod); - } + for (Resp.Result item : Resp.Result.arrayFrom(resp.getData().getResult())) list.add(item.getVod()); return Result.string(list); } @Override public String detailContent(List ids) throws Exception { - if (!login) checkLogin(); - String bvid = ids.get(0); - String bvid2aidUrl = "https://api.bilibili.com/x/web-interface/archive/stat?bvid=" + bvid; - JSONObject bvid2aidResp = new JSONObject(OkHttp.string(bvid2aidUrl, header)); - String aid = bvid2aidResp.getJSONObject("data").getLong("aid") + ""; - String detailUrl = "https://api.bilibili.com/x/web-interface/view?aid=" + aid; - JSONObject detailResp = new JSONObject(OkHttp.string(detailUrl, header)); - JSONObject detailData = detailResp.getJSONObject("data"); - - String defaultQn = "120"; - /* - 6 240P 极速 仅mp4方式支持 - 16 360P 流畅 - 32 480P 清晰 - 64 720P 高清 web端默认值 - B站前端需要登录才能选择,但是直接发送请求可以不登录就拿到720P的取流地址 - 无720P时则为720P60 - 74 720P60 高帧率 需要认证登录账号 - 80 1080P 高清 TV端与APP端默认值 - 需要认证登录账号 - 112 1080P+ 高码率 大多情况需求认证大会员账号 - 116 1080P60 高帧率 大多情况需求认证大会员账号 - 120 4K 超清 需要fnval&128=128且fourk=1 - 大多情况需求认证大会员账号 - 125 HDR 真彩色 仅支持dash方式 - 需要fnval&64=64 - 大多情况需求认证大会员账号 - 126 杜比视界 仅支持dash方式 - 需要fnval&512=512 - 大多情况需求认证大会员账号 - 127 8K 超高清 仅支持dash方式 - 需要fnval&1024=1024 - 大多情况需求认证大会员账号 - */ - - String playurldata = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + detailData.getString("cid") + "&qn=" + defaultQn + "&fnval=4048&fourk=1"; - JSONObject response = new JSONObject(OkHttp.string(playurldata, header)); - JSONObject data = response.getJSONObject("data"); - JSONArray acceptDescription = data.getJSONArray("accept_description"); - JSONArray acceptQuality = data.getJSONArray("accept_quality"); - ArrayList tempQuality = new ArrayList<>(); - ArrayList playFrom = new ArrayList<>(); - for (int i = 0; i < acceptQuality.length(); i++) { - if (!login) { // Check login and set up quality - if (acceptQuality.optInt(i) > 32) - continue; - } else if (vip == 0) { // Check vip and set up quality - if (acceptQuality.optInt(i) > 80) - continue; - } - playFrom.add(acceptDescription.getString(i)); - tempQuality.add(acceptQuality.getString(i)); - } - StringBuilder plist = new StringBuilder(); - for (String Quality : tempQuality) { - ArrayList playList = new ArrayList<>(); - JSONArray pages = detailData.getJSONArray("pages"); - int length = pages.length(); - for (int i = 0; i < length; i++) { - JSONObject page = pages.getJSONObject(i); - long cid = page.getLong("cid"); - String playUrl = i + "$" + aid + "+" + cid + "+" + Quality; - playList.add(playUrl); - } - plist.append(TextUtils.join("#", playList)).append("$$$"); - } + String id = ids.get(0); + String api = "https://api.bilibili.com/x/web-interface/archive/stat?bvid=" + id; + String json = OkHttp.string(api, header); + Resp resp = Resp.objectFrom(json); + String aid = resp.getData().getAid(); + api = "https://api.bilibili.com/x/web-interface/view?aid=" + aid; + json = OkHttp.string(api, header); + Resp.Data detail = Resp.objectFrom(json).getData(); Vod vod = new Vod(); - vod.setVodId(bvid); - vod.setVodName(detailData.getString("title")); - vod.setVodPic(detailData.getString("pic")); - vod.setTypeName(detailData.getString("tname")); - vod.setVodRemarks(detailData.getLong("duration") / 60 + "分鐘"); - vod.setVodContent(detailData.getString("desc")); - vod.setVodPlayFrom(TextUtils.join("$$$", playFrom)); - vod.setVodPlayUrl(plist.toString()); + vod.setVodId(id); + vod.setVodPic(detail.getPic()); + vod.setVodName(detail.getTitle()); + vod.setTypeName(detail.getType()); + vod.setVodContent(detail.getDesc()); + vod.setVodRemarks(detail.getDuration() / 60 + "分鐘"); + + api = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + detail.getCid() + "&qn=120&fnval=4048&fourk=1"; + json = OkHttp.string(api, header); + Resp.Data play = Resp.objectFrom(json).getData(); + List playList = new ArrayList<>(); + for (String quality : play.getAcceptQuality()) { + List vodItems = new ArrayList<>(); + for (Resp.Page page : detail.getPages()) vodItems.add(page.getPart() + "$" + aid + "+" + page.getCid() + "+" + quality); + playList.add(TextUtils.join("#", vodItems)); + } + + vod.setVodPlayFrom(TextUtils.join("$$$", play.getAcceptDescription())); + vod.setVodPlayUrl(TextUtils.join("$$$", playList)); return Result.string(vod); } @@ -224,164 +138,76 @@ public class Bili extends Spider { String[] ids = id.split("\\+"); String aid = ids[0]; String cid = ids[1]; - String Qn = ids[2]; - String urls = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + cid + "&qn=" + Qn + "&fnval=4048&fourk=1"; - // 视频链接时效性限制 2 小时, 得重新请求,暂不处理1 + String qn = ids[2]; + + String api = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + cid + "&qn=" + qn + "&fnval=4048&fourk=1"; + String json = OkHttp.string(api, header); + Resp resp = Resp.objectFrom(json); + Dash dash = resp.getData().getDash(); String videoList = "", audioList = ""; - JSONObject resp = new JSONObject(OkHttp.string(urls, header)).optJSONObject("data").optJSONObject("dash"); - JSONArray video = resp.optJSONArray("video"); - JSONArray audio = resp.optJSONArray("audio"); - for (int i = 0; i < video.length(); i++) { - JSONObject videoDash = video.getJSONObject(i); - if (videoDash.getString("id").equals(Qn)) { - videoList = getDashMedia(videoDash); + for (Dash.Media video : dash.getVideo()) { + if (video.getId().equals(qn)) { + videoList = getMedia(video); break; } } - for (int i = 0; i < audio.length(); i++) { - JSONObject audioDash = audio.getJSONObject(i); - Iterator keys = vod_audio_id.keys(); - while (keys.hasNext()) { - String key = keys.next(); - if (audioDash.getString("id").equals(key)) { - audioList = getDashMedia(audioDash); + for (Dash.Media audio : dash.getAudio()) { + for (String key : audios.keySet()) { + if (audio.getId().equals(key)) { + audioList = getMedia(audio); break; } } } - String mpd = getDash(resp, videoList, audioList); - String dashUrl = "data:application/dash+xml;base64," + Base64.encodeToString(mpd.getBytes(), 0); - return Result.get().url(dashUrl).header(header).string(); + + String mpd = getMpd(dash, videoList, audioList); + String url = "data:application/dash+xml;base64," + Base64.encodeToString(mpd.getBytes(), 0); + return Result.get().url(url).header(header).string(); } - public static String getDashMedia(JSONObject dash) throws Exception { - JSONObject vod_audio_id = new JSONObject(); - vod_audio_id.put("30280", "192000"); - vod_audio_id.put("30232", "132000"); - vod_audio_id.put("30216", "64000"); - String qnid = dash.getString("id"); - int codecid = dash.getInt("codecid"); - String media_codecs = dash.getString("codecs"); - Integer media_bandwidth = dash.getInt("bandwidth"); - String media_startWithSAP = dash.getString("startWithSap"); - String media_mimeType = dash.getString("mimeType"); - String media_BaseURL = dash.getString("baseUrl").replace("&", "&"); - String media_SegmentBase_indexRange = dash.getJSONObject("SegmentBase").getString("indexRange"); - String media_SegmentBase_Initialization = dash.getJSONObject("SegmentBase").getString("Initialization"); - String mediaType = media_mimeType.split("/")[0]; - String media_type_params = ""; - - if (mediaType.equals("video")) { - Integer media_frameRate = dash.getInt("frameRate"); - String media_sar = dash.getString("sar"); - Integer media_width = dash.getInt("width"); - Integer media_height = dash.getInt("height"); - media_type_params = String.format("height='%d' width='%d' frameRate='%d' sar='%s'", media_height, media_width, media_frameRate, media_sar); - } else if (mediaType.equals("audio")) { - String audioSamplingRate = vod_audio_id.getString(qnid); - media_type_params = String.format("numChannels='2' sampleRate='%s'", audioSamplingRate); + private String getMedia(Dash.Media media) { + if (media.getMimeType().startsWith("video")) { + return getAdaptationSet(media, String.format(Locale.getDefault(), "height='%s' width='%s' frameRate='%s' sar='%s'", media.getHeight(), media.getWidth(), media.getFrameRate(), media.getSar())); + } else if (media.getMimeType().startsWith("audio")) { + return getAdaptationSet(media, String.format("numChannels='2' sampleRate='%s'", audios.get(media.getId()))); + } else { + return ""; } + } - qnid += "_" + codecid; - - return String.format( + private String getAdaptationSet(Dash.Media media, String params) { + String id = media.getId() + "_" + media.getCodecId(); + String type = media.getMimeType().split("/")[0]; + String baseUrl = media.getBaseUrl().replace("&", "&"); + return String.format(Locale.getDefault(), "\n" + - " \n" + - " \n" + - " %s\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " ", - mediaType, qnid, media_bandwidth, media_codecs, media_mimeType, media_type_params, media_startWithSAP, media_BaseURL, - media_SegmentBase_indexRange, media_SegmentBase_Initialization); + "\n" + + "\n" + + "%s\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "", + type, + id, media.getBandWidth(), media.getCodecs(), media.getMimeType(), params, media.getStartWithSap(), + baseUrl, + media.getSegmentBase().getIndexRange(), + media.getSegmentBase().getInitialization()); } - - public static String getDash(JSONObject ja, String videoList, String audioList) throws Exception { - Integer duration = ja.getInt("duration"); - Integer minBufferTime = ja.getInt("minBufferTime"); - return String.format( - "\n" + - " \n" + - " %s\n" + - " %s\n" + - " \n" + + private String getMpd(Dash dash, String videoList, String audioList) { + return String.format(Locale.getDefault(), + "\n" + + "\n" + + "%s\n" + + "%s\n" + + "\n" + "", - duration, minBufferTime, duration, videoList, audioList); + dash.getDuration(), dash.getMinBufferTime(), + dash.getDuration(), + videoList, + audioList); } - - private void checkLogin() throws Exception { - login = new JSONObject(OkHttp.string("https://api.bilibili.com/x/web-interface/nav", header)).getJSONObject("data").getBoolean("isLogin"); - boolean qrCode = Prefers.getBoolean("BiliQRCode", true); - if (!login && qrCode) getQRCode(); - } - - private void getQRCode() { - try { - String json = OkHttp.string("https://passport.bilibili.com/x/passport-login/web/qrcode/generate?source=main-mini", null); - JSONObject data = new JSONObject(json).getJSONObject("data"); - Init.run(() -> showQRCode(data)); - } catch (Exception ignored) { - } - } - - private void showQRCode(JSONObject data) { - try { - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(Utils.dp2px(240), Utils.dp2px(240)); - ImageView image = new ImageView(Init.context()); - image.setScaleType(ImageView.ScaleType.CENTER_CROP); - image.setImageBitmap(QRCode.getBitmap(data.getString("url"), 240, 2)); - FrameLayout frame = new FrameLayout(Init.context()); - params.gravity = Gravity.CENTER; - frame.addView(image, params); - dialog = new AlertDialog.Builder(Init.getActivity()).setView(frame).setOnDismissListener(this::dismiss).show(); - dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - Init.execute(() -> startService(data)); - Init.show("請使用 BiliBili App 掃描二維碼"); - } catch (Exception ignored) { - } - } - - private void startService(JSONObject data) { - service = Executors.newScheduledThreadPool(1); - service.scheduleAtFixedRate(() -> { - try { - String qr = data.getString("qrcode_key"); - String url = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + qr + "&source=main_mini"; - String json = OkHttp.string(url, header); - url = new JSONObject(json).getJSONObject("data").getString("url"); - if (!TextUtils.isEmpty(url)) setCookie(url); - } catch (Exception ignored) { - } - }, 1, 1, TimeUnit.SECONDS); - } - - private void setCookie(String url) { - StringBuilder cookie = new StringBuilder(); - String[] aa = Uri.parse(url).getQuery().split("&"); - for (String a : aa) cookie.append(a).append(";"); - Prefers.put("BiliCookie", cookie.toString()); - Init.show("請重新進入播放頁"); - stopService(); - } - - private void stopService() { - if (service != null) service.shutdownNow(); - Init.run(this::dismiss); - } - - private void dismiss(DialogInterface dialog) { - Prefers.put("BiliQRCode", false); - stopService(); - } - - private void dismiss() { - try { - if (dialog != null) dialog.dismiss(); - } catch (Exception ignored) { - } - } -} +} \ No newline at end of file