diff --git a/pom.xml b/pom.xml index c5fa807..dc05015 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,6 @@ - com.alibaba @@ -96,6 +95,11 @@ 1.15 + + com.google.zxing + core + 3.4.1 + @@ -115,7 +119,9 @@ 复制正式文件 - + diff --git a/src/main/java/com/yutou/qqbot/QQBotApplication.java b/src/main/java/com/yutou/qqbot/QQBotApplication.java index 8bc2643..dd22940 100644 --- a/src/main/java/com/yutou/qqbot/QQBotApplication.java +++ b/src/main/java/com/yutou/qqbot/QQBotApplication.java @@ -6,7 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class QQBotApplication { - public static final String version="QQBot v.1.2.10.1"; + public static final String version="QQBot v.1.2.11"; public static void main(String[] args) { System.out.println("version = " + version); SpringApplication.run(QQBotApplication.class, args); diff --git a/src/main/java/com/yutou/qqbot/QQBotManager.java b/src/main/java/com/yutou/qqbot/QQBotManager.java index 2e87c7f..a4df99f 100644 --- a/src/main/java/com/yutou/qqbot/QQBotManager.java +++ b/src/main/java/com/yutou/qqbot/QQBotManager.java @@ -7,6 +7,7 @@ import com.yutou.qqbot.models.Commands.Bangumi; import com.yutou.qqbot.models.Commands.BTDownload; import com.yutou.qqbot.models.Commands.System.*; import com.yutou.qqbot.models.Model; +import com.yutou.qqbot.models.WebSign.BiliBiliMangeSign; import com.yutou.qqbot.models.WebSign.Tsdm; import com.yutou.qqbot.models.XiaoMi.MiRouter; import com.yutou.qqbot.models.setu.GetSeTu; @@ -49,6 +50,7 @@ public class QQBotManager { Model.classList.add(MiRouter.class); Model.classList.add(GetSeTu.class); Model.classList.add(BTDownload.class); + Model.classList.add(BiliBiliMangeSign.class); } private static QQBotManager botManager = null; private Bot bot; diff --git a/src/main/java/com/yutou/qqbot/bilibili/BiliBiliManga.java b/src/main/java/com/yutou/qqbot/bilibili/BiliBiliManga.java new file mode 100644 index 0000000..a86767a --- /dev/null +++ b/src/main/java/com/yutou/qqbot/bilibili/BiliBiliManga.java @@ -0,0 +1,16 @@ +package com.yutou.qqbot.bilibili; + +import com.alibaba.fastjson.JSONObject; +import com.yutou.qqbot.utlis.HttpTools; + +public class BiliBiliManga { + public static JSONObject sign(){ + JSONObject body=new JSONObject(); + body.put("platform","android"); + return BiliBiliUtils.http_post("https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn", HttpTools.toUrlParams(body)); + } + + public static void main(String[] args) { + BiliBiliManga.sign(); + } +} diff --git a/src/main/java/com/yutou/qqbot/bilibili/BiliBiliUtils.java b/src/main/java/com/yutou/qqbot/bilibili/BiliBiliUtils.java new file mode 100644 index 0000000..b1061ef --- /dev/null +++ b/src/main/java/com/yutou/qqbot/bilibili/BiliBiliUtils.java @@ -0,0 +1,173 @@ +package com.yutou.qqbot.bilibili; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.yutou.qqbot.utlis.ConfigTools; +import org.springframework.util.StringUtils; + +import javax.net.ssl.HttpsURLConnection; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +public class BiliBiliUtils { + 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 = outputStream.toString(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); + e.printStackTrace(); + } + return null; + } + + public static JSONObject http_post(String url, String body) { + JSONObject json = null; + try { + if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + oldBiliBiliHttpTime = System.currentTimeMillis(); + } + HttpURLConnection connection = getBiliHttpPost(url, getCookie()); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + OutputStream connectionOutputStream = null; + if (!StringUtils.isEmpty(body)) { + connectionOutputStream = connection.getOutputStream(); + connectionOutputStream.write(body.getBytes(StandardCharsets.UTF_8)); + connectionOutputStream.flush(); + } + connection.connect(); + if(connection.getResponseCode()==400){ + return null; + } + 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 = outputStream.toString(StandardCharsets.UTF_8); + outputStream.close(); + try { + json = JSON.parseObject(str); + json.put("cookie", connection.getHeaderField("Set-Cookie")); + return json; + } catch (Exception e) { + 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) { + e.printStackTrace(); + } + return json; + } + + public static String getCookie() { + if (StringUtils.isEmpty(ConfigTools.readFile(new File("bilibili.cookie")))) { + + return ""; + } + JSONObject json = JSONObject.parseObject(ConfigTools.readFile(new File("bilibili.cookie"))); + StringBuilder builder = new StringBuilder(); + for (String s : json.keySet()) { + builder.append(s).append("=").append(json.getString(s)).append(";"); + + } + return builder.toString(); + } + + public static HttpURLConnection getBiliHttpPost(String url, String cookie) throws Exception { + if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + oldBiliBiliHttpTime = System.currentTimeMillis(); + } + HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setDoInput(true); + setConnection(cookie, connection); + return connection; + } + + public static HttpURLConnection getBiliHttpGet(String url, String cookie) throws IOException { + if (System.currentTimeMillis() - oldBiliBiliHttpTime < 1000) { + try { + Thread.sleep(500); + } catch (InterruptedException ignored) { + } + oldBiliBiliHttpTime = System.currentTimeMillis(); + } + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + setConnection(cookie, connection); + connection.setReadTimeout(5000); + connection.setConnectTimeout(5000); + return connection; + } + + private static void setConnection(String cookie, HttpURLConnection connection) { + 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", ".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"); + } + + public static JSONObject getLoginInfo() { + JSONObject jsonObject = BiliBiliUtils.http_get("https://api.bilibili.com/x/web-interface/nav"); + if (jsonObject == null) { + jsonObject = new JSONObject(); + jsonObject.put("code", "-1"); + jsonObject.put("data", new JSONObject()); + } + return jsonObject; + } +} diff --git a/src/main/java/com/yutou/qqbot/bilibili/BiliLogin.java b/src/main/java/com/yutou/qqbot/bilibili/BiliLogin.java new file mode 100644 index 0000000..9c09583 --- /dev/null +++ b/src/main/java/com/yutou/qqbot/bilibili/BiliLogin.java @@ -0,0 +1,73 @@ +package com.yutou.qqbot.bilibili; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yutou.qqbot.utlis.ConfigTools; +import com.yutou.qqbot.utlis.HttpTools; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +public class BiliLogin { + + + public JSONObject login(){ + JSONObject login= JSONObject.parseObject(HttpTools.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(() -> 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=JSONObject.parseObject(HttpTools.post("https://passport.bilibili.com/qrcode/getLoginInfo",bd.getBytes(StandardCharsets.UTF_8))); + if(json.containsKey("code")&&json.getInteger("code")==0){ + System.out.println("json = " + json); + String _url=json.getJSONObject("data").getString("url"); + Map map=HttpTools.getUrlParams(_url); + + JSONObject cookie=new JSONObject(); + JSONArray array=new JSONArray(); + for (String key : map.keySet()) { + cookie.put(key,map.get(key)); + } + System.out.println(array); + + JSONObject tmp=BiliBiliUtils.http_post(_url,""); + System.out.println("tmp = " + tmp); + String sid=tmp.getString("cookie"); + sid=sid.split("sid=")[1]; + sid=sid.split(";")[0]; + cookie.put("sid",sid); + cookie.put("Domain",".bilibili.com"); + ConfigTools.saveFile(new File("bilibili.cookie"),cookie.toJSONString()); + cancel(); + } + } + },0,3000); + + } + public boolean testLogin(){ + JSONObject jsonObject = BiliBiliUtils.getLoginInfo(); + return jsonObject.getInteger("code")==0; + } + + + public static void main(String[] args) { + BiliLogin login = new BiliLogin(); + login.testLogin(); + } +} diff --git a/src/main/java/com/yutou/qqbot/models/Model.java b/src/main/java/com/yutou/qqbot/models/Model.java index 576b825..03c8206 100644 --- a/src/main/java/com/yutou/qqbot/models/Model.java +++ b/src/main/java/com/yutou/qqbot/models/Model.java @@ -44,6 +44,7 @@ public abstract class Model implements ModelInterface { public static final String ROUTER_ADD = "!添加设备"; public static final String ROUTER_DEL = "!删除设备"; public static final String BT_DOWNLOAD = "下载bt"; + public static final String BILI_MANGA_SIGN="!B站漫画签到"; } diff --git a/src/main/java/com/yutou/qqbot/models/WebSign/BiliBiliMangeSign.java b/src/main/java/com/yutou/qqbot/models/WebSign/BiliBiliMangeSign.java new file mode 100644 index 0000000..e728728 --- /dev/null +++ b/src/main/java/com/yutou/qqbot/models/WebSign/BiliBiliMangeSign.java @@ -0,0 +1,60 @@ +package com.yutou.qqbot.models.WebSign; + +import com.yutou.qqbot.QQBotManager; +import com.yutou.qqbot.bilibili.BiliBiliManga; +import com.yutou.qqbot.bilibili.BiliLogin; +import com.yutou.qqbot.models.Model; +import com.yutou.qqbot.utlis.QRCodeUtils; +import net.mamoe.mirai.event.events.MessageEvent; + +import java.io.File; + +public class BiliBiliMangeSign extends Model { + @Override + public boolean isUserPublic() { + return false; + } + + @Override + public String[] getUsePowers() { + return new String[]{ + QQFromCommands.BILI_MANGA_SIGN + }; + } + + @Override + public void onMessage(Long qq, MessageEvent event, boolean isGroup) { + super.onMessage(qq, event, isGroup); + if(event.getMessage().contentToString().equals(QQFromCommands.BILI_MANGA_SIGN)){ + String msg; + if(new BiliLogin().testLogin()){ + if(BiliBiliManga.sign()==null){ + msg="B站漫画已经签到过了"; + }else{ + msg="B站漫画签到完成"; + } + QQBotManager.getInstance().sendMessage(qq,msg); + }else{ + String url = new BiliLogin().login().getString("url"); + File code = QRCodeUtils.createQRCode("bili_login",url); + QQBotManager.getInstance().sendMessage(code,qq,"B站未登录,请扫码登陆后再试"); + } + } + } + + @Override + public void onTime(String time) { + super.onTime(time); + if("00:01:00".equals(time)){ + if(new BiliLogin().testLogin()){ + String msg; + if(BiliBiliManga.sign()==null){ + msg="B站漫画已经签到过了"; + }else{ + msg="B站漫画签到完成"; + } + QQBotManager.getInstance().sendMessage(msg); + } + } + } +} diff --git a/src/main/java/com/yutou/qqbot/utlis/ConfigTools.java b/src/main/java/com/yutou/qqbot/utlis/ConfigTools.java index d916c49..567ccd0 100644 --- a/src/main/java/com/yutou/qqbot/utlis/ConfigTools.java +++ b/src/main/java/com/yutou/qqbot/utlis/ConfigTools.java @@ -11,6 +11,7 @@ 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 BiliBili = "bilibili.cookie"; static { try { @@ -104,7 +105,7 @@ public class ConfigTools { String tmp; StringBuilder str = new StringBuilder(); while ((tmp = reader.readLine()) != null) { - str.append(tmp); + str.append(tmp).append("\n"); } reader.close(); return str.toString(); diff --git a/src/main/java/com/yutou/qqbot/utlis/HttpTools.java b/src/main/java/com/yutou/qqbot/utlis/HttpTools.java index acab6be..ec63cf0 100644 --- a/src/main/java/com/yutou/qqbot/utlis/HttpTools.java +++ b/src/main/java/com/yutou/qqbot/utlis/HttpTools.java @@ -7,6 +7,8 @@ import org.jetbrains.annotations.NotNull; import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.*; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -89,11 +91,13 @@ public class HttpTools { //connection.addRequestProperty("User-Agent", getExtUa()); //connection.addRequestProperty("content-type", "application/json"); connection.addRequestProperty("charset", "UTF-8"); - OutputStream outputStream = connection.getOutputStream(); - //System.out.println(new String(body)); - outputStream.write(body); - outputStream.flush(); - outputStream.close(); + if(body!=null) { + OutputStream outputStream = connection.getOutputStream(); + //System.out.println(new String(body)); + outputStream.write(body); + outputStream.flush(); + outputStream.close(); + } connection.connect(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); while ((tmp = reader.readLine()) != null) { @@ -124,11 +128,11 @@ public class HttpTools { Set keys = json.keySet(); for (String key : keys) { try { - string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key), "UTF-8")); + string.append("&").append(key).append("=").append(URLEncoder.encode(json.getString(key), StandardCharsets.UTF_8)); } catch (Exception e) { e.printStackTrace(); try { - string.append("&").append(URLEncoder.encode(key, "UTF-8")).append("="); + string.append("&").append(URLEncoder.encode(key, StandardCharsets.UTF_8)).append("="); // string += "&" + key + "="; } catch (Exception e1) { string.append("&").append(key).append("="); @@ -139,6 +143,17 @@ public class HttpTools { string = new StringBuilder(string.substring(1, string.length()).replaceAll(" ", "")); return string.toString(); } + public static Map getUrlParams(String url){ + Map map=new HashMap<>(); + if(url.contains("?")){ + String param=url.split("\\?")[1]; + String[] params=param.split("&"); + for (String par : params) { + map.put(par.split("=")[0],par.split("=")[1]); + } + } + return map; + } public static void main(String[] args) { JSONObject json = new JSONObject(); diff --git a/src/main/java/com/yutou/qqbot/utlis/QRCodeUtils.java b/src/main/java/com/yutou/qqbot/utlis/QRCodeUtils.java new file mode 100644 index 0000000..3b9050e --- /dev/null +++ b/src/main/java/com/yutou/qqbot/utlis/QRCodeUtils.java @@ -0,0 +1,58 @@ +package com.yutou.qqbot.utlis; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class QRCodeUtils { + private static final int BLACK = 0xFF000000; + private static final int WHITE = 0xFFFFFFFF; + + + public static File createQRCode(String codeName,String value){ + try { + String imageType = "jpg";// 图片类型 + MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); + Map hints = new HashMap(); + hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); + BitMatrix bitMatrix = multiFormatWriter.encode(value, BarcodeFormat.QR_CODE, 400, 400, hints); + if(!new File("QRCode").exists()){ + boolean mkdirs = new File(("QRCode")).mkdirs(); + System.out.println("create QRCode dir is = "+mkdirs); + } + File file1 = new File("QRCode"+File.separator+ codeName + "." + imageType); + writeToFile(bitMatrix, imageType, file1); + return file1; + } catch (WriterException | IOException e) { + e.printStackTrace(); + } + return null; + } + private static BufferedImage toBufferedImage(BitMatrix matrix) { + int width = matrix.getWidth(); + int height = matrix.getHeight(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); + } + } + return image; + } + + private static void writeToFile(BitMatrix matrix, String format, File file) throws IOException { + BufferedImage image = toBufferedImage(matrix); + if (!ImageIO.write(image, format, file)) { + throw new IOException("Could not write an image of format " + format + " to " + file); + } + } +} diff --git a/src/main/java/com/yutou/qqbot/utlis/WebClient.java b/src/main/java/com/yutou/qqbot/utlis/WebClient.java index baa871c..b6d3f7a 100644 --- a/src/main/java/com/yutou/qqbot/utlis/WebClient.java +++ b/src/main/java/com/yutou/qqbot/utlis/WebClient.java @@ -49,21 +49,24 @@ public class WebClient { json.getString("domain"), json.getString("path"), containsDate ? new Date(t) : new Date(), - json.getBoolean("secure"), - json.getBoolean("httpOnly") + json.containsKey("secure")?json.getBoolean("secure"):false, + json.containsKey("httpOnly")?json.getBoolean("httpOnly"):false ); list.add(cookie); } return list; } - + static boolean headless=false; + public static void setHeadless(boolean headless){ + WebClient.headless=headless; + } public static ChromeOptions getOptions() { ChromeOptions options = new ChromeOptions(); // options.addArguments("--disable-gpu"); // options.addArguments("blink-settings=imagesEnabled=false"); String headless = RedisTools.get("headless"); - if("true".equals(headless)) { + if("true".equals(headless)||WebClient.headless) { options.addArguments("--headless"); } options.addArguments("--no-sandbox");