From 693a4f0f63c6cf781b382a4a11e717cdd3952638 Mon Sep 17 00:00:00 2001 From: QAIU <736226400@qq.com> Date: Mon, 16 Dec 2024 15:54:06 +0800 Subject: [PATCH] =?UTF-8?q?1.=20P115=E7=BD=91=E7=9B=98=E8=A7=A3=E6=9E=90BU?= =?UTF-8?q?G=202.=20=E5=AE=8C=E5=96=84onedrive=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/qaiu/parser/impl/P115Tool.java | 4 +- .../java/cn/qaiu/parser/impl/PodTool.java | 229 ++++++++++++++++-- 2 files changed, 212 insertions(+), 21 deletions(-) diff --git a/parser/src/main/java/cn/qaiu/parser/impl/P115Tool.java b/parser/src/main/java/cn/qaiu/parser/impl/P115Tool.java index 29fa46a..c848695 100644 --- a/parser/src/main/java/cn/qaiu/parser/impl/P115Tool.java +++ b/parser/src/main/java/cn/qaiu/parser/impl/P115Tool.java @@ -67,9 +67,9 @@ public class P115Tool extends PanBase { // 第二次请求 // share_code={dataKey}&receive_code={dataPwd}&file_id={file_id} - - clientNoRedirects.postAbs(SECOND_REQUEST_URL) + client.postAbs(SECOND_REQUEST_URL) .putHeaders(header) + .putHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .sendForm(MultiMap.caseInsensitiveMultiMap() .set("share_code", shareLinkInfo.getShareKey()) .set("receive_code", shareLinkInfo.getSharePassword()) diff --git a/parser/src/main/java/cn/qaiu/parser/impl/PodTool.java b/parser/src/main/java/cn/qaiu/parser/impl/PodTool.java index 433e445..c95e27c 100644 --- a/parser/src/main/java/cn/qaiu/parser/impl/PodTool.java +++ b/parser/src/main/java/cn/qaiu/parser/impl/PodTool.java @@ -1,10 +1,21 @@ package cn.qaiu.parser.impl; +import cn.qaiu.WebClientVertxInit; import cn.qaiu.entity.ShareLinkInfo; import cn.qaiu.parser.PanBase; import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.core.WorkerExecutor; import io.vertx.core.json.JsonObject; +import io.vertx.core.net.ProxyOptions; import io.vertx.uritemplate.UriTemplate; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -21,40 +32,208 @@ public class PodTool extends PanBase { * -> @content.downloadUrl */ - private static final String api = "https://api.onedrive.com/v1.0/drives/{cid}/items/{cid20}?authkey={authkey}"; + + // https://onedrive.live.com/redir?resid=ABFD0A26E47D3458!4699&e=OggA4s&migratedtospo=true&redeem=aHR0cHM6Ly8xZHJ2Lm1zL3UvcyFBbGcwZmVRbUN2MnJwRnZ1NDQ0aGc1eVZxRGNLP2U9T2dnQTRz + private static final String API_TEMPLATE = "https://onedrive.live.com/embed" + + "?id={resid}&resid={resid1}" + + "&cid={cid}" + + "&redeem={redeem}" + + "&migratedtospo=true&embed=1"; + + private static final String TOKEN_API = "https://api-badgerp.svc.ms/v1.0/token"; + + private static final Pattern redirectUrlRegex = - Pattern.compile("=(?.+)!(?.+)&authkey=(?.+)&e=(?.+)"); + Pattern.compile("resid=(?[^!]+)!(?[^&]+).+&redeem=(?.+).*"); public PodTool(ShareLinkInfo shareLinkInfo) { super(shareLinkInfo); } public Future parse() { - clientNoRedirects.getAbs(shareLinkInfo.getShareUrl()).send().onSuccess(r0 -> { + + + /* + * POST https://api-badgerp.svc.ms/v1.0/token + * Content-Type: application/json + * + * { + * "appid": "00000000-0000-0000-0000-0000481710a4" + * } + */ + // https://my.microsoftpersonalcontent.com/_api/v2.0/shares/u!aHR0cHM6Ly8xZHJ2Lm1zL3UvcyFBbGcwZmVRbUN2MnJwRnZ1NDQ0aGc1eVZxRGNLP2U9T2dnQTRz/driveitem?%24select=*%2Cocr%2CwebDavUrl + // https://onedrive.live.com/embed?id=ABFD0A26E47D3458!4698&resid=ABFD0A26E47D3458!4698&cid=abfd0a26e47d3458&redeem=aHR0cHM6Ly8xZHJ2Lm1zL3UvYy9hYmZkMGEyNmU0N2QzNDU4L0lRUllOSDNrSmdyOUlJQ3JXaElBQUFBQUFTWGlubWZ2WmNxYUQyMXJUQjIxVmg4&migratedtospo=true&embed=1 + + + clientNoRedirects.getAbs(shareLinkInfo.getShareUrl() == null ? shareLinkInfo.getStandardUrl() : + shareLinkInfo.getShareUrl()).send().onSuccess(r0 -> { String location = r0.getHeader("Location"); Matcher matcher = redirectUrlRegex.matcher(location); - if (matcher.find()) { - var cid= matcher.group("cid"); - var cid2= matcher.group("cid2"); - var authkey= matcher.group("authkey"); - client.getAbs(UriTemplate.of(api)) - .setTemplateParam("cid", cid) - .setTemplateParam("cid20", cid + "!" + cid2) - .setTemplateParam("authkey", authkey).send() - .onSuccess(res -> { - JsonObject jsonObject = asJson(res); - // System.out.println(jsonObject); - complete(jsonObject.getString("@content.downloadUrl")); - }) - .onFailure(handleFail()); + if (!matcher.find()) { + fail("Location格式错误"); + return; } + String redeem = matcher.group("redeem"); + String cid1 = matcher.group("cid1"); + String cid2 = cid1 + "!" + matcher.group("cid2"); + + clientNoRedirects.getAbs(UriTemplate.of(API_TEMPLATE)) + .setTemplateParam("resid", cid2) + .setTemplateParam("resid1", cid2) + .setTemplateParam("cid", cid1.toLowerCase()) + .setTemplateParam("redeem", redeem) + .proxy(new ProxyOptions().setHost("127.0.0.1").setPort(7890)) + .send() + .onSuccess(r1 -> { + String auth = + r1.cookies().stream().filter(c -> c.startsWith("BadgerAuth=")).findFirst().orElse(""); + if (auth.isEmpty()) { + fail("Error BadgerAuth not fount"); + return; + } + String token = auth.split(";")[0].split("=")[1]; + + try { + + String url = matcherUrl(r1.bodyAsString()); + + sendHttpRequest(url, token).onSuccess(body -> { + Matcher matcher1 = + Pattern.compile("\"downloadUrl\":\"(?https?://[^\s\"]+)").matcher(body); + if (matcher1.find()) { + complete(matcher1.group("url")); + } else { + fail(); + } + }).onFailure(handleFail()); + } catch (Exception ignored) { + sendHttpRequest2(token, redeem).onSuccess(res -> { + try { + complete(new JsonObject(res).getString("@content.downloadUrl")); + } catch (Exception ignored1) { + fail(); + } + }).onFailure(handleFail()); + } + + }).onFailure(handleFail()); }).onFailure(handleFail()); + return promise.future(); + } + + private String matcherUrl(String html) { + + // 正则表达式来匹配 URL + String urlRegex = "'action'.+(?https://.+)'\\)"; + Pattern urlPattern = Pattern.compile(urlRegex); + Matcher urlMatcher = urlPattern.matcher(html); + + if (urlMatcher.find()) { + String url = urlMatcher.group("url"); + System.out.println("URL: " + url); + return url; + } + throw new RuntimeException("URL匹配失败"); + } + + + private String matcherToken(String html) { + // 正则表达式来匹配 inputElem.value 中的 Token + String tokenRegex = "inputElem\\.value\\s*=\\s*'([^']+)'"; + Pattern tokenPattern = Pattern.compile(tokenRegex); + Matcher tokenMatcher = tokenPattern.matcher(html); + + if (tokenMatcher.find()) { + String token = tokenMatcher.group(1); + System.out.println("Token: " + token); + return token; + } + throw new RuntimeException("token匹配失败"); + } + + public Future sendHttpRequest2(String token, String redeem) { + Promise promise = Promise.promise(); + // 构造 HttpClient + HttpClient client = HttpClient.newHttpClient(); + + // 构造请求的 URI 和头部信息 + // https://onedrive.live.com/redir?cid=abfd0a26e47d3458&resid=ABFD0A26E47D3458!4465&ithint=file%2cxlsx&e=Ao2uSU&migratedtospo=true&redeem=aHR0cHM6Ly8xZHJ2Lm1zL3gvYy9hYmZkMGEyNmU0N2QzNDU4L0VWZzBmZVFtQ3YwZ2dLdHhFUUFBQUFBQlRQRWVDMTZfZk1EYk5FTjhEdTRta1E_ZT1BbzJ1U1U + String url = ("https://my.microsoftpersonalcontent.com/_api/v2.0/shares/u!%s/driveItem?$select=content" + + ".downloadUrl").formatted(redeem); + String authorizationHeader = "Badger " + token; + + // 构建请求 + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)) + .header("Authorization", authorizationHeader) + .build(); + + // 发送请求并处理响应 + client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) + .thenApply(response -> { + System.out.println("Response Status Code: " + response.statusCode()); + System.out.println("Response Body: " + response.body()); + promise.complete(response.body()); + return null; + }); return promise.future(); } + public Future sendHttpRequest(String url, String token) { + // 创建一个 WorkerExecutor 用于异步执行阻塞的 HTTP 请求 + WorkerExecutor executor = WebClientVertxInit.get().createSharedWorkerExecutor("http-client-worker"); + + Promise promise = Promise.promise(); + executor.executeBlocking(() -> { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = null; + + try { + // 构造请求 + request = HttpRequest.newBuilder() + .uri(new URI(url)) + .header("accept", "text/html,application/xhtml+xml,application/xml;q=0.9," + + "image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;" + + "v=b3;q=0.7") + .header("accept-language", "zh-CN,zh;q=0.9") + .header("cache-control", "no-cache") + .header("content-type", "application/x-www-form-urlencoded") + .header("dnt", "1") + .header("origin", "https://onedrive.live.com") + .header("pragma", "no-cache") + .header("priority", "u=0, i") + .header("referer", "https://onedrive.live.com/") + .header("sec-ch-ua", "\"Chromium\";v=\"130\", \"Google Chrome\";v=\"130\", " + + "\"Not?A_Brand\";v=\"99\"") + .header("sec-ch-ua-mobile", "?0") + .header("sec-ch-ua-platform", "\"Windows\"") + .header("sec-fetch-dest", "iframe") + .header("sec-fetch-mode", "navigate") + .header("sec-fetch-site", "cross-site") + .header("upgrade-insecure-requests", "1") + .header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537" + + ".36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36") + .POST(HttpRequest.BodyPublishers.ofString("badger_token=" + token)) + .build(); + + // 发起请求并获取响应 + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // 返回响应体 + promise.complete(response.body()); + return null; + } catch (URISyntaxException | IOException | InterruptedException e) { + throw new RuntimeException(e); + } + }); + + return promise.future(); + } + + //https://onedrive.live.com/redir?resid=ABFD0A26E47D3458!4699&e=OggA4s&migratedtospo=true&redeem=aHR0cHM6Ly8xZHJ2Lm1zL3UvcyFBbGcwZmVRbUN2MnJwRnZ1NDQ0aGc1eVZxRGNLP2U9T2dnQTRz -// public static void main(String[] args) { + public static void main(String[] args) { // Matcher matcher = redirectUrlRegex.matcher("https://onedrive.live.com/redir?resid=ABFD0A26E47D3458!4698" + // "&authkey=!ACpvXghP5xhG_cg&e=hV98W1"); // if (matcher.find()) { @@ -62,6 +241,18 @@ public class PodTool extends PanBase { // System.out.println(matcher.group("cid2")); // System.out.println(matcher.group("authkey")); // } + // appid 5cbed6ac-a083-4e14-b191-b4ba07653de2 5cbed6ac-a083-4e14-b191-b4ba07653de2 + // https://my.microsoftpersonalcontent.com/personal/abfd0a26e47d3458/_layouts/15/embed.aspx?UniqueId=e47d3458-0a26-20fd-80ab-5b1200000000&Translate=false&ApiVersion=2.0 + // https://my.microsoftpersonalcontent.com/personal/abfd0a26e47d3458/_layouts/15/embed.aspx?UniqueId=6b0900d6-abcf-44ce-b7bf-7b626bcbe4b8&Translate=false&ApiVersion=2.0 + // https://1drv.ms/u/s!Alg0feQmCv2rpFvu444hg5yVqDcK?e=OggA4s + // https://1drv.ms/u/c/abfd0a26e47d3458/EVg0feQmCv0ggKtbEgAAAAABqGv8K6HmOwLRsvokyV5fUg?e=iqoRc0 + // https://1drv.ms/u/c/abfd0a26e47d3458/EVg0feQmCv0ggKtaEgAAAAAB-lF1qjkfv5OqdrT9VSMDMw + new PodTool(ShareLinkInfo.newBuilder().shareUrl("https://1drv.ms/x/c/abfd0a26e47d3458" + + "/EVg0feQmCv0ggKtxEQAAAAABTPEeC16_fMDbNEN8Du4mkQ?e=Ao2uSU") + .build()) + .parse().onSuccess(res -> { + System.out.println(res); + }); -// } + } }