diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/CommonUtils.java b/web-service/src/main/java/cn/qaiu/lz/common/util/CommonUtils.java index 78f5f46..8c855cd 100644 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/CommonUtils.java +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/CommonUtils.java @@ -1,11 +1,38 @@ package cn.qaiu.lz.common.util; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; + public class CommonUtils { - public static String parseURL(String urlPrefix, String url) { + public static String adaptShortPaths(String urlPrefix, String url) { if (!url.startsWith(urlPrefix)) { url = urlPrefix + url; } + if (url.endsWith(".html")) { + url = url.substring(0, url.length() - 5); + } return url.substring(urlPrefix.length()); } + + public static Map getURLParams(String url) throws MalformedURLException { + URL fullUrl = new URL(url); + String query = fullUrl.getQuery(); + String[] params = query.split("&"); + Map map = new HashMap<>(); + for (String param : params) { + if (!param.contains("=")) { + throw new RuntimeException("解析URL异常: 匹配不到参数中的="); + } + int endIndex = param.indexOf('='); + String key = param.substring(0, endIndex); + String value = param.substring(endIndex + 1); + map.put(key, value); + } + return map; + } + } diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/FcTool.java b/web-service/src/main/java/cn/qaiu/lz/common/util/FcTool.java index 452a824..24ddf59 100644 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/FcTool.java +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/FcTool.java @@ -28,7 +28,7 @@ public class FcTool { "&scenario=share&unique_name={uname}"; public static Future parse(String data, String code) { - String dataKey = CommonUtils.parseURL(SHARE_URL_PREFIX, data); + String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data); Promise promise = Promise.promise(); diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/FjTool.java b/web-service/src/main/java/cn/qaiu/lz/common/util/FjTool.java index 34b00f6..577862a 100644 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/FjTool.java +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/FjTool.java @@ -28,7 +28,7 @@ public class FjTool { "&devType=6&uuid={uuid}×tamp={ts}&auth={auth}"; public static Future parse(String data) { - String dataKey = CommonUtils.parseURL(SHARE_URL_PREFIX, data); + String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data); Promise promise = Promise.promise(); WebClient client = WebClient.create(VertxHolder.getVertxInstance(), diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java b/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java index d49bcb3..6adfda7 100644 --- a/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/UcTool.java @@ -27,7 +27,7 @@ public class UcTool { private static final String THIRD_REQUEST_URL = API_URL_PREFIX + "file/download?entry=ft&fr=pc&pr=UCBrowser"; public static Future parse(String data, String code) { - var dataKey = CommonUtils.parseURL(SHARE_URL_PREFIX, data); + var dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data); var passcode = (code == null) ? "" : code; Promise promise = Promise.promise(); var client = WebClient.create(VertxHolder.getVertxInstance()); diff --git a/web-service/src/main/java/cn/qaiu/lz/common/util/YeTool.java b/web-service/src/main/java/cn/qaiu/lz/common/util/YeTool.java new file mode 100644 index 0000000..e212a08 --- /dev/null +++ b/web-service/src/main/java/cn/qaiu/lz/common/util/YeTool.java @@ -0,0 +1,102 @@ +package cn.qaiu.lz.common.util; + +import cn.qaiu.vx.core.util.VertxHolder; +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.client.WebClient; +import io.vertx.uritemplate.UriTemplate; +import org.apache.commons.lang3.StringUtils; + +import java.net.MalformedURLException; +import java.util.Base64; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 123网盘 + */ +public class YeTool { + public static final String SHARE_URL_PREFIX = "https://www.123pan.com/s/"; + public static final String FIRST_REQUEST_URL = SHARE_URL_PREFIX + "{key}.html"; + private static final String GET_FILE_INFO_URL = "https://www.123pan.com/a/api/share/get?limit=100&next=1&orderBy" + + "=file_name&orderDirection=asc&shareKey={shareKey}&SharePwd={pwd}&ParentFileId=0&Page=1&event" + + "=homeListFile&operateType=1"; + + public static Future parse(String data, String code) { + + String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data); + Promise promise = Promise.promise(); + WebClient client = WebClient.create(VertxHolder.getVertxInstance()); + + client.getAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("key", dataKey).send().onSuccess(res -> { + + String html = res.bodyAsString(); + Pattern compile = Pattern.compile("window.g_initialProps\\s*=\\s*(.*);"); + Matcher matcher = compile.matcher(html); + + if (!matcher.find()) { + System.out.println("err"); + return; + } + String fileInfoString = matcher.group(1); + JsonObject fileInfoJson = new JsonObject(fileInfoString); + JsonObject resJson = fileInfoJson.getJsonObject("res"); + JsonObject resListJson = fileInfoJson.getJsonObject("reslist"); + + if (resJson == null || resJson.getInteger("code") != 0) { + promise.fail(dataKey + " 解析到异常JSON: "+resJson); + return; + } + String shareKey = resJson.getJsonObject("data").getString("ShareKey"); + if (resListJson == null || resListJson.getInteger("code") != 0) { + // 加密分享 + if (StringUtils.isNotEmpty(code)) { + client.getAbs(UriTemplate.of(GET_FILE_INFO_URL)) + .setTemplateParam("shareKey", shareKey) + .setTemplateParam("pwd", code) + .send().onSuccess(res2 -> { + JsonObject infoJson = res2.bodyAsJsonObject(); + if (infoJson.getInteger("code") != 0) { + return; + } + JsonObject getFileInfoJson = + infoJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0); + getFileInfoJson.put("ShareKey", shareKey); + getDownUrl(promise, client, getFileInfoJson); + }); + } else { + promise.fail(dataKey + " 该分享需要密码"); + } + return; + } + + JsonObject reqBodyJson = resListJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0); + reqBodyJson.put("ShareKey", shareKey); + getDownUrl(promise, client, reqBodyJson); + }); + + return promise.future(); + } + + private static void getDownUrl(Promise promise, WebClient client, JsonObject reqBodyJson) { + System.out.println(reqBodyJson); + client.postAbs("https://www.123pan.com/a/api/share/download/info").sendJsonObject(reqBodyJson).onSuccess(res2 -> { + JsonObject downURLJson = res2.bodyAsJsonObject(); + System.out.println(downURLJson); + if (downURLJson.getInteger("code") != 0) { + return; + } + String downURL = downURLJson.getJsonObject("data").getString("DownloadURL"); + try { + Map urlParams = CommonUtils.getURLParams(downURL); + String params = urlParams.get("params"); + byte[] decodeByte = Base64.getDecoder().decode(params); + promise.complete(new String(decodeByte)); + } catch (MalformedURLException e) { + promise.fail("urlParams解析异常" + e.getMessage()); + } + }); + } +} diff --git a/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java b/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java index 81848f6..74d3215 100644 --- a/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java +++ b/web-service/src/main/java/cn/qaiu/lz/web/http/ServerApi.java @@ -64,6 +64,11 @@ public class ServerApi { response.putHeader("location", resUrl).setStatusCode(302).end(); promise.complete(); }).onFailure(t -> promise.fail(t.fillInStackTrace())); + } else if (url.contains(YeTool.SHARE_URL_PREFIX)) { + YeTool.parse(url, pwd).onSuccess(resUrl -> { + response.putHeader("location", resUrl).setStatusCode(302).end(); + promise.complete(); + }).onFailure(t -> promise.fail(t.fillInStackTrace())); } else if (url.contains("lanzou")) { String urlDownload; try { @@ -196,4 +201,30 @@ public class ServerApi { } return FcTool.parse(id, code); } + + @RouteMapping(value = "/ye/:id", method = RouteMethod.GET) + public void YeParse(HttpServerResponse response, String id) { + String code = ""; + if (id.contains("@")) { + String[] ids = id.split("@"); + id = ids[0]; + code = ids[1]; + } + YeTool.parse(id, code).onSuccess(resUrl -> response.putHeader("location", resUrl) + .setStatusCode(302).end()).onFailure(t -> { + response.putHeader(CONTENT_TYPE, "text/html;charset=utf-8"); + response.end(t.getMessage()); + }); + } + + @RouteMapping(value = "/json/ye/:id", method = RouteMethod.GET) + public Future YeParseJson(HttpServerResponse response, String id) { + String code = ""; + if (id.contains("@")) { + String[] ids = id.split("@"); + id = ids[0]; + code = ids[1]; + } + return YeTool.parse(id, code); + } } diff --git a/web-service/src/main/resources/http-tools/pan-ye.http b/web-service/src/main/resources/http-tools/pan-ye.http new file mode 100644 index 0000000..89d71f5 --- /dev/null +++ b/web-service/src/main/resources/http-tools/pan-ye.http @@ -0,0 +1,84 @@ +### 123网盘 +# auto_redirect 0 +# filename libc++_shared.so +# r L7PQ1A +# s 16864619537565b1bbecb509ef377f6e8487a6a99b +# t 1686461953 +# v 5 +# x-mf-biz-cid 4010bf7a-c68c-42d2-bdf4-13e2b5545904-a0d664 +# @no-redirect +# @no-cookie-jar +https://download-cdn.123pan.cn/123-670/af2b7957/1813857424-0/af2b7957d3f4062a06a7b9ef6a3d5a9e?t=1686461953&s=16864619537565b1bbecb509ef377f6e8487a6a99b&r=L7PQ1A&filename=libc%2B%2B_shared.so&auto_redirect=0 + + + +### 获取下载 +# FileID S3keyFlag Size Etag + +# @no-redirect +# @no-cookie-jar +POST https://www.123pan.com/a/api/share/download/info +Content-Type:application/json;charset=UTF-8 + +{ + "ShareKey": "iaKtVv-qOECd", + "FileID": 2193733, + "S3keyFlag": "1813857424-0", + "Size": 976880, + "Etag": "af2b7957d3f4062a06a7b9ef6a3d5a9e" +} + +### +POST https://www.123pan.com/a/api/share/download/info +Content-Type:application/json;charset=UTF-8 + +{ + "res": { + "code": 0, + "message": "ok", + "data": { + "UserNickName": "15********0", + "UserID": 1815268665, + "ShareName": "libc++_shared.so", + "HasPwd": false, + "Expiration": "2099-01-01T00:00:00+08:00", + "CreateAt": "2023-06-10T13:36:44+08:00", + "Expired": false, + "ShareKey": "iaKtVv-qOECd", + "HeadImage": "https://thirdwx.qlogo.cn/mmopen/vi_32/0G2KQrJ4105icYkK0zBADdHhxyM2W7Q5jf0xh9OyfOM6INOaB3Mgov6CUjdibz43ZvhnZm2MLe8zgd1cZv4C72XQ/132", + "IsVip": false, + "DisplayStatus": 1 + } + }, + "reslist": { + "code": 0, + "message": "ok", + "data": { + "Next": "-1", + "Len": 1, + "IsFirst": true, + "Expired": false, + "InfoList": [ + { + "FileId": 2193733, + "FileName": "libc++_shared.so", + "Type": 0, + "Size": 976880, + "ContentType": "0", + "S3KeyFlag": "1813857424-0", + "CreateAt": "2023-06-10T13:36:12+08:00", + "UpdateAt": "2023-06-10T13:36:44+08:00", + "Etag": "af2b7957d3f4062a06a7b9ef6a3d5a9e", + "DownloadUrl": "", + "Status": 5, + "ParentFileId": 0, + "Category": 0, + "PunishFlag": 0, + "StorageNode": "m0", + "checked": true + } + ] + } + }, + "publicPath": "https://www.123pan.com/a/api/" +} diff --git a/web-service/src/main/resources/http-tools/test.http b/web-service/src/main/resources/http-tools/test.http index 2e861e7..8db0302 100644 --- a/web-service/src/main/resources/http-tools/test.http +++ b/web-service/src/main/resources/http-tools/test.http @@ -152,3 +152,14 @@ GET http://127.0.0.1:6400/json/fc/30646fefc8bf936a4766ab8a5e GET http://127.0.0.1:6400/fc/e5079007dc31226096628870c7@QAIU #https://v2.fangcloud.com/sharing/e5079007dc31226096628870c7 + +### 123 +GET http://127.0.0.1:6400/json/ye/iaKtVv-qOECd + +### 123 +# @no-redirect +GET http://127.0.0.1:6400/ye/iaKtVv-qOECd@asdads + +### 123 +# @no-redirect +GET http://127.0.0.1:6400/parser?url=https://www.123pan.com/s/iaKtVv-6OECd.html&pwd=DcGe