From 0a296cc93741a2fdb74d5401ee7b79d3d3f2f433 Mon Sep 17 00:00:00 2001 From: qaiu <736226400@qq.com> Date: Sun, 28 Jan 2024 15:26:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=93=9D=E5=A5=8F=E4=BA=91?= =?UTF-8?q?=E4=BC=98=E4=BA=AB=E8=A7=A3=E6=9E=90=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- bin/run.bat | 1 + .../main/java/cn/qaiu/parser/IPanTool.java | 3 + .../main/java/cn/qaiu/parser/impl/IzTool.java | 78 +++++++++++++++++++ .../src/main/java/cn/qaiu/util/AESUtils.java | 54 +++++++++++-- .../test/java/qaiu/web/test/TestAESUtil.java | 6 ++ .../src/main/resources/http-tools/pan-iz.http | 18 +++++ .../src/main/resources/http-tools/test.http | 11 ++- 8 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 parser/src/main/java/cn/qaiu/parser/impl/IzTool.java create mode 100644 web-service/src/main/resources/http-tools/pan-iz.http diff --git a/README.md b/README.md index 1182385..c9a583b 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/qaiu/netdisk-fast-download)](https://github.com/qaiu/netdisk-fast-download/releases/tag/0.1.6-releases) ## 项目介绍 -网盘直链解析工具能把网盘分享下载链接转化为直链,已支持蓝奏云/奶牛快传/移动云云空间/小飞机盘/亿方云/123云盘等,支持私密分享。 +网盘直链解析工具能把网盘分享下载链接转化为直链,已支持蓝奏云/蓝奏云优享/奶牛快传/移动云云空间/小飞机盘/亿方云/123云盘等,支持私密分享。 *重要声明:本项目仅供学习参考;请不要将此项目用于任何商业用途,否则可能带来严重的后果。* @@ -24,6 +24,9 @@ - [蓝奏云 (lz)](https://pc.woozooo.com/) - [ ] 登录, 上传, 下载, 分享 - [X] 直链解析 +- [蓝奏云优享 (iz)](https://https://www.ilanzou.com/) + - [ ] 登录, 上传, 下载, 分享 + - [X] 直链解析 - [奶牛快传 (cow)](https://cowtransfer.com/) - [ ] 登录, 上传, 下载, 分享 - [X] 直链解析 diff --git a/bin/run.bat b/bin/run.bat index cb2f28c..615ca8a 100644 --- a/bin/run.bat +++ b/bin/run.bat @@ -5,6 +5,7 @@ for /f "delims=X" %%i in ('dir /b %LIB_DIR%\netdisk-fast-download.jar') do ( set LAUNCH_JAR=%LIB_DIR%%%i ) +set "JAVA_HOME=D:\App\dragonwell-17.0.3.0.3+7-GA" "%JAVA_HOME%\bin\java.exe" -Xmx512M -Dfile.encoding=utf8 -jar %LAUNCH_JAR% %* pause diff --git a/parser/src/main/java/cn/qaiu/parser/IPanTool.java b/parser/src/main/java/cn/qaiu/parser/IPanTool.java index 2ca2082..283e17f 100644 --- a/parser/src/main/java/cn/qaiu/parser/IPanTool.java +++ b/parser/src/main/java/cn/qaiu/parser/IPanTool.java @@ -19,6 +19,7 @@ public interface IPanTool { case "le" -> new LeTool(key, pwd); case "ws" -> new WsTool(key, pwd); case "qq" -> new QQTool(key, pwd); + case "iz" -> new IzTool(key, pwd); default -> { throw new UnsupportedOperationException("未知分享类型"); } @@ -39,6 +40,8 @@ public interface IPanTool { return new YeTool(url, pwd); } else if (url.startsWith(FjTool.SHARE_URL_PREFIX) || url.startsWith(FjTool.SHARE_URL_PREFIX2)) { return new FjTool(url, pwd); + } else if (url.startsWith(IzTool.SHARE_URL_PREFIX)) { + return new IzTool(url, pwd); } else if (url.contains(LzTool.LINK_KEY)) { return new LzTool(url, pwd); } else if (url.startsWith(LeTool.SHARE_URL_PREFIX)) { diff --git a/parser/src/main/java/cn/qaiu/parser/impl/IzTool.java b/parser/src/main/java/cn/qaiu/parser/impl/IzTool.java new file mode 100644 index 0000000..0980e57 --- /dev/null +++ b/parser/src/main/java/cn/qaiu/parser/impl/IzTool.java @@ -0,0 +1,78 @@ +package cn.qaiu.parser.impl; + +import cn.qaiu.parser.IPanTool; +import cn.qaiu.parser.PanBase; +import cn.qaiu.util.AESUtils; +import cn.qaiu.util.CommonUtils; +import io.vertx.core.Future; +import io.vertx.core.MultiMap; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.client.WebClient; +import io.vertx.uritemplate.UriTemplate; + +import java.util.UUID; + +/** + * 小飞机网盘 + * + * @version V016_230609 + */ +public class IzTool extends PanBase implements IPanTool { + + public static final String SHARE_URL_PREFIX = "https://www.ilanzou.com/s/"; + private static final String API_URL_PREFIX = "https://api.ilanzou.com/unproved/"; + + private static final String FIRST_REQUEST_URL = API_URL_PREFIX + "recommend/list?devType=6&devModel=Chrome&extra" + + "=2&shareId={shareId}&type=0&offset=1&limit=60"; + + private static final String SECOND_REQUEST_URL = API_URL_PREFIX + "file/redirect?downloadId={fidEncode}&enable=1" + + "&devType=6&uuid={uuid}×tamp={ts}&auth={auth}"; + + public IzTool(String key, String pwd) { + super(key, pwd); + } + + public Future parse() { + String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key); + + WebClient client = clientNoRedirects; + String shareId = String.valueOf(AESUtils.idEncryptIz(dataKey)); + + // 第一次请求 获取文件信息 + // POST https://api.feijipan.com/ws/recommend/list?devType=6&devModel=Chrome&extra=2&shareId=146731&type=0&offset=1&limit=60 + client.postAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("shareId", shareId).send().onSuccess(res -> { + JsonObject resJson = res.bodyAsJsonObject(); + if (resJson.getInteger("code") != 200) { + fail(FIRST_REQUEST_URL + " 返回异常: " + resJson); + return; + } + if (resJson.getJsonArray("list").size() == 0) { + fail(FIRST_REQUEST_URL + " 解析文件列表为空: " + resJson); + return; + } + // 文件Id + String fileId = resJson.getJsonArray("list").getJsonObject(0).getString("fileIds"); + // 其他参数 + long nowTs = System.currentTimeMillis(); + String tsEncode = AESUtils.encrypt2HexIz(Long.toString(nowTs)); + String uuid = UUID.randomUUID().toString(); + String fidEncode = AESUtils.encrypt2HexIz(fileId + "|"); + String auth = AESUtils.encrypt2HexIz(fileId + "|" + nowTs); + // 第二次请求 + client.getAbs(UriTemplate.of(SECOND_REQUEST_URL)) + .setTemplateParam("fidEncode", fidEncode) + .setTemplateParam("uuid", uuid) + .setTemplateParam("ts", tsEncode) + .setTemplateParam("auth", auth).send().onSuccess(res2 -> { + MultiMap headers = res2.headers(); + if (!headers.contains("Location")) { + fail(SECOND_REQUEST_URL + " 未找到重定向URL: \n" + res.headers()); + return; + } + promise.complete(headers.get("Location")); + }).onFailure(handleFail(SECOND_REQUEST_URL)); + }).onFailure(handleFail(FIRST_REQUEST_URL)); + + return promise.future(); + } +} diff --git a/parser/src/main/java/cn/qaiu/util/AESUtils.java b/parser/src/main/java/cn/qaiu/util/AESUtils.java index 37d559d..471d8e7 100644 --- a/parser/src/main/java/cn/qaiu/util/AESUtils.java +++ b/parser/src/main/java/cn/qaiu/util/AESUtils.java @@ -34,7 +34,10 @@ public class AESUtils { public static final String CIPHER_AES2 = "YbQHZqK/PdQql2+7ATcPQHREAxt0Hn0Ob9v317QirZM="; + public static final String CIPHER_AES2_IZ = "1uQFS3sNeHd/bCrmrQpflXREAxt0Hn0Ob9v317QirZM="; + public static final String CIPHER_AES0; + public static final String CIPHER_AES0_IZ; /** * 秘钥长度 @@ -59,6 +62,7 @@ public class AESUtils { static { try { CIPHER_AES0 = decryptByBase64AES(CIPHER_AES2, CIPHER_AES); + CIPHER_AES0_IZ = decryptByBase64AES(CIPHER_AES2_IZ, CIPHER_AES); } catch (IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException(e); @@ -154,6 +158,15 @@ public class AESUtils { } } + public static String encrypt2HexIz(String source) { + try { + return encryptHexByAES(source, CIPHER_AES0_IZ); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | + BadPaddingException e) { + throw new RuntimeException("加密失败: "+ e.getMessage()); + } + } + /** * AES解密 * @@ -214,10 +227,14 @@ public class AESUtils { 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'L', 'R', 'S', 'I', 'J', 'K'}; - - private static int decodeChar(char c) { - for (int i = 0; i < array.length; i++) { - if (c == array[i]) { + private static final char[] arrayIz = + {'Y', 'y', '0', 'Z', 'z', 'N', 'n', 'M', 'I', '6', 'm', 'W', 'w', '1', 'X', 'x', 'L', 'l', 'K', '7', 'k', + 'i', 'U', 'u', '2', 'V', 'v', 'J', 'j', '8', 'G', 'g', 'F', 'S', 's', '3', 'T', 't', 'H', 'h', + 'f', 'E', 'e', 'D', 'Q', 'q', '4', 'R', 'r', '9', 'd', 'a', 'C', 'c', 'B', 'O', 'o', '5', 'P', + 'p', 'b', 'A'}; + private static int decodeChar(char c, char[] keys) { + for (int i = 0; i < keys.length; i++) { + if (c == keys[i]) { return i; } } @@ -226,21 +243,46 @@ public class AESUtils { // id解密 public static int idEncrypt(String str) { + return idEncrypt0(str, array, 2, 2); + } + + // ================================蓝奏优享版Id解密========================================== // + public static int idEncryptIz(String str) { +// idEncrypt(e) { +// let t = 1 +// , n = 0; +// if ("" != e && e.length > 4) { +// let r; +// e = e.substring(3, e.length - 1); +// for (let v = 0; v < e.length; v++) +// r = e.charAt(e.length - v - 1), +// n += this.decodeChar(r) * t, +// t *= 62 +// } +// return n +// }, + + return idEncrypt0(str, arrayIz, 3, 1); + } + + public static int idEncrypt0(String str, char[] keys, int x1, int x2) { // 倍数 int multiple = 1; int result = 0; if (StringUtils.isNotEmpty(str) && str.length() > 4) { - str = str.substring(2, str.length() - 2); + str = str.substring(x1, str.length() - x2); char c; for (int i = 0; i < str.length(); i++) { c = str.charAt(str.length() - i - 1); - result += decodeChar(c) * multiple; + result += decodeChar(c, keys) * multiple; multiple = multiple * 62; } } return result; } + + // ========================== musetransfer加密相关 =========================== //length用户要求产生字符串的长度 diff --git a/parser/src/test/java/qaiu/web/test/TestAESUtil.java b/parser/src/test/java/qaiu/web/test/TestAESUtil.java index c452c77..67a4a48 100644 --- a/parser/src/test/java/qaiu/web/test/TestAESUtil.java +++ b/parser/src/test/java/qaiu/web/test/TestAESUtil.java @@ -50,6 +50,12 @@ public class TestAESUtil { Assert.assertEquals(146731, AESUtils.idEncrypt("7jy0zlv")); } + // 蓝奏优享 + @Test + public void testIzIdDecode() { + Assert.assertEquals(26216, AESUtils.idEncryptIz("lGFndCM")); + } + @Test public void test00() throws IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException { diff --git a/web-service/src/main/resources/http-tools/pan-iz.http b/web-service/src/main/resources/http-tools/pan-iz.http new file mode 100644 index 0000000..34a4af8 --- /dev/null +++ b/web-service/src/main/resources/http-tools/pan-iz.http @@ -0,0 +1,18 @@ +### +POST https://api.ilanzou.com/unproved/recommend/list?shareId=26216 + + +### +#@no-redirect +https://api.ilanzou.com/unproved/file/redirect?downloadId=DC3D647979EE315935D1687834F05914&enable=1&devType=6&uuid=46vk1ImPHKt1Mr2cRu5wA×tamp=B11E6A597CB93B55D87A338AEDDFBE45&auth=8BF7415F1AA0BB02278336F3C11EBD0B25654EAAB68588D5E8C4974ACAD88935 + +### +#@no-redirect +https://api.ilanzou.com/unproved/file/redirect?downloadId=DC3D647979EE315935D1687834F05914&enable=1&devType=6&uuid=46vk1ImPHKt1Mr2cRu5wA×tamp=90A417B68D70B35311FACC72EEE63291&auth=849E8A34873CA37147A5FE110912FCBF836D8BD5D37626FBCBD8A3F6F42A7A8B + + + +### +#@no-redirect +https://dl.lanosso.com/disk/2024/01/28/9/14733029/1706414002788330.gz?attname=testgles.c&sign=9ef76e9a270dbe5e9401c8f4c2ae0d68&t=65b5f826 + diff --git a/web-service/src/main/resources/http-tools/test.http b/web-service/src/main/resources/http-tools/test.http index dfd164f..015c5eb 100644 --- a/web-service/src/main/resources/http-tools/test.http +++ b/web-service/src/main/resources/http-tools/test.http @@ -4,11 +4,14 @@ GET http://127.0.0.1:6400/parser?url=https://lanzoux.com/ia2cntg ### 蓝奏云 # @no-redirect -GET http://127.0.0.1:6400/parser?url=https://lanzoux.com/iNvid035jgcb +GET http://127.0.0.1:6400/json/parser?url=https://wwsd.lanzoue.com/iLany1e9bbbi ### 蓝奏云 # @no-redirect GET http://127.0.0.1:6400/lz/i6SqHmp1yfc +### 蓝奏云https://acgtools.lanzoui.com/iUr7Qnu3sxc https://wwn.lanzouy.com/tp/ihLkw1gezutg https://wwn.lanzouy.com/ihLkw1gezutg +# @no-redirect +GET http://127.0.0.1:6400/lz/ihLkw1gezutg ### 蓝奏云 # @no-redirect @@ -17,6 +20,12 @@ GET http://127.0.0.1:6400/lz/icBp6qqj82b@QAIU ### 蓝奏云 GET http://127.0.0.1:6400/json/lz/ia2cntg +### 蓝奏云优享 +GET http://127.0.0.1:6400/json/iz/lGFndCM + +### +GET http://127.0.0.1:6400/json/parser?url=https://www.ilanzou.com/s/lGFndCM + ### 奶牛 GET http://127.0.0.1:6400/json/cow/9a644fe3e3a748 Referer: https://cowtransfer.com/