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.Log; 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; 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 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 getMsgList(byte[] bytes, List 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) { if (live.getInfo().getRoomid().equals(data.getRoomid())) { return live; } } return null; } private static JSONObject getLiveInfo(int roomId) { return http_get("https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=" + roomId); } public static String getLiveTitle(int roomId) { JSONObject json = LiveInfoManager.getInstance().getInfo(roomId); if (json != null) { return json.getJSONObject("data").getJSONObject("room_info").getString("title"); } return null; } public static boolean isLivePlayer(int roomId) { JSONObject json = LiveInfoManager.getInstance().getInfo(roomId); if (json == null) { return false; } BilibiliUpInfo upData = new BilibiliUpInfo(); upData.setRoomid(roomId); //Log.i("直播检测:" + roomId + " > " + (json.getJSONObject("data").getJSONObject("room_info").getInteger("live_status") == 1) + " 录播器:" + liveContains(upData)); return json.getJSONObject("data").getJSONObject("room_info").getInteger("live_status") == 1; } private static void checkLiveSave(int roomId) { BilibiliUpInfo upData = new BilibiliUpInfo(); upData.setRoomid(roomId); Live live = liveContains(upData); if (live == null) { live = new Live(); live.add(roomId, !StringUtils.isEmpty(AppTools.readFile(new File("cookies.json")))); try { live.start(); } catch (Exception e) { com.yutou.bilibili.Tools.Log.e(e); } } if (!SaveLive.getInstance().checkLive(roomId)) { SaveLive.getInstance().addLive(roomId); } } public static class LiveGiftConfig { @Resource IBiliBiliLiveService service; private static LiveGiftConfig config; public static List giftDataList = new ArrayList<>(); public static LiveGiftConfig getInstance() { if (config == null) { config = new LiveGiftConfig(); } return config; } private LiveGiftConfig() { init(); } public void init() { giftDataList = new ArrayList<>(); JSONObject json = http_get("https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/giftConfig?platform=pc"); JSONArray list = json.getJSONObject("data").getJSONArray("list"); for (Object o : list) { JSONObject item = (JSONObject) o; 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")); giftDataList.add(data); } } } public static class LiveInfoManager { private static LiveInfoManager manager; private Map infoMap; public static LiveInfoManager getInstance() { if (manager == null) { manager = new LiveInfoManager(); } return manager; } private LiveInfoManager() { infoMap = new HashMap<>(); } public synchronized void check(List list) { for (BilibiliUpInfo upInfo : list) { JSONObject json = getLiveInfo(upInfo.getRoomid()); if (json != null) { infoMap.put(upInfo.getRoomid(), json); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } Log.i("信息map数量:"+infoMap.size()); } public synchronized void check(int roomId) { JSONObject json = getLiveInfo(roomId); if (json != null) { Log.i("登记直播:"+roomId); infoMap.put(roomId, json); }else{ infoMap.remove(roomId); } } public synchronized JSONObject getInfo(int roomId) { if (!infoMap.containsKey(roomId)) { //check(roomId); return null; } return infoMap.get(roomId); } } }