Compare commits

..

24 Commits

Author SHA1 Message Date
qaiu
18478b2a0b Update README.md 2023-08-20 10:36:39 +08:00
qaiu
dde54ed9cc Merge pull request #13 from qaiu/dev
蓝奏云规则修改, 奶牛功能增强
2023-08-20 10:35:02 +08:00
qaiu
3c56a7183e 修复蓝奏云pan解析错误的问题#12 2023-08-20 10:29:00 +08:00
QAIU
38a3ae8a56 Merge remote-tracking branch 'origin/dev' into dev 2023-08-19 17:29:04 +08:00
QAIU
00b30331eb 奶牛快传支持下载zip目录分享#11, core框架优化 2023-08-19 17:28:30 +08:00
qaiu
8397c24715 Update README.md 2023-08-13 00:58:12 +08:00
qaiu
3ee113e81f Update README.md 2023-08-13 00:55:20 +08:00
qaiu
cde641c8db Update README.md 2023-08-13 00:54:21 +08:00
QAIU
30cd2f5850 奶牛快传支持下载zip目录分享#11, core框架优化 2023-08-11 15:28:37 +08:00
QAIU
71066ded98 core框架优化 2023-08-10 14:54:45 +08:00
qaiu
8441954075 修复123pan解析错误的问题#9 2023-08-10 01:49:41 +08:00
qaiu
5e0568fa0e 代码结构优化;修复123pan解析错误的问题#9 2023-08-10 01:45:39 +08:00
qaiu
594e9af71d 代码结构优化;修复123pan解析错误的问题#9 2023-08-10 01:42:34 +08:00
qaiu
9bc7e9aa26 代码结构优化
修复123pan解析错误的问题#9
2023-08-10 01:38:20 +08:00
qaiu
5805edf0a9 Merge pull request #10 from qaiu/master
Master
2023-08-10 01:17:11 +08:00
qaiu
9614a36fc2 fixed 123pan /b/api/share/download/info->/a/api/share/download/info 2023-08-10 00:59:09 +08:00
QAIU
f45031c3f1 代码结构优化, 异常处理优化 2023-08-08 17:36:36 +08:00
QAIU
28e0542c8e 代码结构优化, 异常处理优化 2023-08-08 11:34:32 +08:00
QAIU
b78a8300c6 0 2023-08-04 17:49:30 +08:00
qaiu
ca06d5ae98 Update README.md 2023-08-02 17:53:04 +08:00
QAIU
0c5e53b86e 0 2023-08-01 14:42:32 +08:00
qaiu
f45e6f3468 前端页面优化 2023-07-31 22:43:23 +08:00
qaiu
08ffec524e 前端页面优化 2023-07-31 22:41:33 +08:00
QAIU
62dea67d69 0 2023-07-31 14:07:12 +08:00
47 changed files with 824 additions and 478 deletions

View File

@@ -1,4 +1,5 @@
# netdisk-fast-download
云盘解析服务 (nfd云解析)
预览地址 https://lz.qaiu.top
[![Java CI with Maven](https://github.com/qaiu/netdisk-fast-download/actions/workflows/maven.yml/badge.svg)](https://github.com/qaiu/netdisk-fast-download/actions/workflows/maven.yml)
@@ -6,6 +7,14 @@
[![vert.x](https://img.shields.io/badge/vert.x-4.4.1-blue)](https://vertx-china.github.io/)
[![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云盘等支持私密分享。
## 应用场景:
1. 游戏:使用本站工具可自动生成高速直流下载器,用于游戏客户端自动化高速下载安装、更新等。
2. 下载:可根据网盘分享的地址解析为直链,方便放到自己网站上供用户下载,节约服务器带宽和磁盘。
3. 音视频:可解析为音视频直链,可直接在网页上播放,高清,高速,节约服务器带宽和磁盘。
## 网盘支持情况:
> 20230722 UC网盘解析失效需要登录
@@ -39,7 +48,7 @@
**TODO:**
- 登录接口, 文件上传/下载/分享后端接口
- 短地址服务
- 前端界面(正则规划)
- 前端界面(建设中...)
**技术栈:**
Jdk17+Vert.x4.4.1

View File

@@ -157,8 +157,8 @@ public class CreateTable {
return sql.substring(0, sql.length() - 1) + ");\r\n";
}
public static void createTable(JDBCPool pool, String tableClassPath) {
Set<Class<?>> tableClassList = ReflectionUtil.getReflections(tableClassPath).getTypesAnnotatedWith(Table.class);
public static void createTable(JDBCPool pool) {
Set<Class<?>> tableClassList = ReflectionUtil.getReflections().getTypesAnnotatedWith(Table.class);
if (tableClassList.isEmpty()) LOGGER.info("Table model class not fount");
tableClassList.forEach(clazz -> {
String createTableSQL = getCreateTableSQL(clazz);

View File

@@ -92,7 +92,7 @@ public class JDBCPoolInit {
private void poolInitExecute(Promise<String> promise) {
// 初始化连接池
pool = JDBCPool.pool(vertx, dbConfig);
CreateTable.createTable(pool, dbConfig.getString("tableClassPath"));
CreateTable.createTable(pool);
promise.complete("init jdbc pool success");
}

View File

@@ -20,6 +20,7 @@
<slf4j.version>2.0.5</slf4j.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<jackson.version>2.14.2</jackson.version>
<logback.version>1.4.6</logback.version>
</properties>
<dependencyManagement>
@@ -39,7 +40,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.6</version>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>

View File

@@ -1,12 +1,12 @@
package cn.qaiu.vx.core;
import cn.qaiu.vx.core.util.ConfigConstant;
import cn.qaiu.vx.core.util.ConfigUtil;
import cn.qaiu.vx.core.util.VertxHolder;
import cn.qaiu.vx.core.verticle.ReverseProxyVerticle;
import cn.qaiu.vx.core.verticle.RouterVerticle;
import cn.qaiu.vx.core.verticle.ServiceVerticle;
import io.vertx.core.*;
import io.vertx.core.impl.launcher.commands.VersionCommand;
import io.vertx.core.json.JsonObject;
import io.vertx.core.shareddata.LocalMap;
import org.slf4j.Logger;
@@ -17,6 +17,8 @@ import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.locks.LockSupport;
import static cn.qaiu.vx.core.util.ConfigConstant.*;
/**
* vertx启动类 需要在主启动类完成回调
* <br>Create date 2021-05-07 10:26:54
@@ -95,7 +97,7 @@ public final class Deploy {
System.out.printf(logoTemplete,
conf.getString("version_app"),
conf.getString("version_vertx"),
VersionCommand.getVersion(),
conf.getString("copyright"),
year
);
@@ -107,10 +109,10 @@ public final class Deploy {
private void deployVerticle() {
tempVertx.close();
LOGGER.info("配置读取成功");
customConfig = globalConfig.getJsonObject(ConfigConstant.CUSTOM);
customConfig = globalConfig.getJsonObject(CUSTOM);
JsonObject vertxConfig = globalConfig.getJsonObject(ConfigConstant.VERTX);
Integer vertxConfigELPS = vertxConfig.getInteger(ConfigConstant.EVENT_LOOP_POOL_SIZE);
JsonObject vertxConfig = globalConfig.getJsonObject(VERTX);
Integer vertxConfigELPS = vertxConfig.getInteger(EVENT_LOOP_POOL_SIZE);
var vertxOptions = vertxConfigELPS == 0 ?
new VertxOptions() : new VertxOptions(vertxConfig);
@@ -121,10 +123,10 @@ public final class Deploy {
VertxHolder.init(vertx);
//配置保存在共享数据中
var sharedData = vertx.sharedData();
LocalMap<String, Object> localMap = sharedData.getLocalMap(ConfigConstant.LOCAL);
localMap.put(ConfigConstant.GLOBAL_CONFIG, globalConfig);
localMap.put(ConfigConstant.CUSTOM_CONFIG, customConfig);
localMap.put(ConfigConstant.SERVER, globalConfig.getJsonObject(ConfigConstant.SERVER));
LocalMap<String, Object> localMap = sharedData.getLocalMap(LOCAL);
localMap.put(GLOBAL_CONFIG, globalConfig);
localMap.put(CUSTOM_CONFIG, customConfig);
localMap.put(SERVER, globalConfig.getJsonObject(SERVER));
var future0 = vertx.createSharedWorkerExecutor("other-handle").executeBlocking(bch -> {
handle.handle(globalConfig);
bch.complete("other handle complete");
@@ -168,7 +170,7 @@ public final class Deploy {
* @return Deployment Options
*/
private DeploymentOptions getWorkDeploymentOptions(String name) {
return getWorkDeploymentOptions(name, customConfig.getInteger(ConfigConstant.ASYNC_SERVICE_INSTANCES));
return getWorkDeploymentOptions(name, customConfig.getInteger(ASYNC_SERVICE_INSTANCES));
}
private DeploymentOptions getWorkDeploymentOptions(String name, int ins) {

View File

@@ -0,0 +1,23 @@
package cn.qaiu.vx.core.annotaions;
import java.lang.annotation.*;
/**
* 拦截器配置注解
* 正则匹配拦截途径
*
* @author <a href="https://qaiu.top">QAIU</a>
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InterceptorConfig {
String pattern() default "";
/**
* 注册顺序,数字越大越先注册
*/
int order() default 0;
}

View File

@@ -6,6 +6,7 @@ import cn.qaiu.vx.core.annotaions.RouteMapping;
import cn.qaiu.vx.core.annotaions.SockRouteMapper;
import cn.qaiu.vx.core.base.BaseHttpApi;
import cn.qaiu.vx.core.enums.MIMEType;
import cn.qaiu.vx.core.interceptor.Interceptor;
import cn.qaiu.vx.core.model.JsonResult;
import cn.qaiu.vx.core.util.*;
import io.vertx.core.Future;
@@ -22,6 +23,7 @@ import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.CorsHandler;
import io.vertx.ext.web.handler.StaticHandler;
import io.vertx.ext.web.handler.TimeoutHandler;
import io.vertx.ext.web.handler.sockjs.SockJSHandler;
import io.vertx.ext.web.handler.sockjs.SockJSHandlerOptions;
import javassist.CtClass;
@@ -38,6 +40,7 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.qaiu.vx.core.util.ConfigConstant.ROUTE_TIME_OUT;
import static io.vertx.core.http.HttpHeaders.*;
/**
@@ -62,10 +65,9 @@ public class RouterHandlerFactory implements BaseHttpApi {
private final String gatewayPrefix;
public RouterHandlerFactory(String routerScanAddress, String gatewayPrefix) {
Objects.requireNonNull(routerScanAddress, "The router package address scan is empty.");
public RouterHandlerFactory(String gatewayPrefix) {
Objects.requireNonNull(gatewayPrefix, "The gateway prefix is empty.");
reflections = ReflectionUtil.getReflections(routerScanAddress);
reflections = ReflectionUtil.getReflections();
this.gatewayPrefix = gatewayPrefix;
}
@@ -173,6 +175,8 @@ public class RouterHandlerFactory implements BaseHttpApi {
route.consumes(mineType);
}
// 设置默认超时
route.handler(TimeoutHandler.create(SharedDataUtil.getCustomConfig().getInteger(ROUTE_TIME_OUT)));
// 先执行拦截方法, 再进入业务请求
route.handler(interceptor);
route.handler(ctx -> handlerMethod(instance, method, ctx)).failureHandler(ctx -> {
@@ -234,10 +238,8 @@ public class RouterHandlerFactory implements BaseHttpApi {
private Handler<RoutingContext> getInterceptor() throws Throwable {
// 配置拦截
Class<?> interceptorClass = Class.forName(SharedDataUtil.getValueForCustomConfig("interceptorClassPath"));
Object handleInstance = ReflectionUtil.newWithNoParam(interceptorClass);
Method doHandle = interceptorClass.getMethod("doHandle");
// 反射调用
return CastUtil.cast(ReflectionUtil.invoke(doHandle, handleInstance));
Interceptor handleInstance = (Interceptor)ReflectionUtil.newWithNoParam(interceptorClass);
return handleInstance.doHandle();
}
/**

View File

@@ -12,8 +12,10 @@ import io.vertx.ext.web.RoutingContext;
public interface Interceptor {
default Handler<RoutingContext> doHandle() {
return this::handle;
return this::beforeHandle;
}
void handle(RoutingContext context);
void beforeHandle(RoutingContext context);
void afterHandle(RoutingContext context);
}

View File

@@ -3,11 +3,14 @@ package cn.qaiu.vx.core.util;
public interface ConfigConstant {
String CUSTOM = "custom";
String VERTX = "vertx";
String EVENT_LOOP_POOL_SIZE = "eventLoopPoolSize";
String LOCAL = "local";
String SERVER = "server";
String GLOBAL_CONFIG = "globalConfig";
String CUSTOM_CONFIG = "customConfig";
String ASYNC_SERVICE_INSTANCES = "asyncServiceInstances";
String IGNORES_REG="ignoresReg";
String BASE_LOCATIONS="baseLocations";
String ROUTE_TIME_OUT="routeTimeOut";
}

View File

@@ -24,6 +24,8 @@ import java.net.URL;
import java.text.ParseException;
import java.util.*;
import static cn.qaiu.vx.core.util.ConfigConstant.BASE_LOCATIONS;
/**
* 基于org.reflection和javassist的反射工具包
* 通过包扫描实现路由地址的注解映射
@@ -33,6 +35,16 @@ import java.util.*;
*/
public final class ReflectionUtil {
/**
* 以默认配置的基础包路径获取反射器
*
* @return Reflections object
*/
public static Reflections getReflections() {
return getReflections(SharedDataUtil.getStringForCustomConfig(BASE_LOCATIONS));
}
/**
* 获取反射器
*
@@ -48,6 +60,7 @@ public final class ReflectionUtil {
} else {
packageAddressList = Collections.singletonList(packageAddress);
}
return getReflections(packageAddressList);
}
@@ -70,11 +83,12 @@ public final class ReflectionUtil {
// 发现注解api层 没有继承父类时 这里反射一直有问题(Scanner SubTypesScanner was not configured)
// 因此这里需要手动配置各种Scanner扫描器 -- https://blog.csdn.net/qq_29499107/article/details/106889781
configurationBuilder.setScanners(
new SubTypesScanner(false), //允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes 会报错.默认为true.
Scanners.SubTypes.filterResultsBy(s -> true), //允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes
// 会报错.默认为true.
new MethodParameterNamesScanner(), //设置方法参数名称 扫描器,否则调用getConstructorParamNames 会报错
new MethodAnnotationsScanner(), //设置方法注解 扫描器, 否则getConstructorsAnnotatedWith,getMethodsAnnotatedWith 会报错
new MemberUsageScanner(), //设置 member 扫描器,否则 getMethodUsage 会报错, 不推荐使用,有可能会报错 Caused by: java.lang.ClassCastException: javassist.bytecode.InterfaceMethodrefInfo cannot be cast to javassist.bytecode.MethodrefInfo
new TypeAnnotationsScanner() //设置类注解 扫描器 ,否则 getTypesAnnotatedWith 会报错
Scanners.MethodsAnnotated, //设置方法注解 扫描器, 否则getConstructorsAnnotatedWith,getMethodsAnnotatedWith 会报错
new MemberUsageScanner(), //设置 member 扫描器,否则 getMethodUsage 会报错
Scanners.TypesAnnotated //设置类注解 扫描器 ,否则 getTypesAnnotatedWith 会报错
);
configurationBuilder.filterInputsBy(filterBuilder);
@@ -98,7 +112,8 @@ public final class ReflectionUtil {
MethodInfo methodInfo = cm.getMethodInfo();
CtClass[] parameterTypes = cm.getParameterTypes();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
LocalVariableAttribute attr =
(LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
boolean flag = true;
boolean flag2 = cm.getModifiers() - 1 != AccessFlag.STATIC;
@@ -110,7 +125,8 @@ public final class ReflectionUtil {
continue;
}
flag = false;
paramMap.put(attr.variableName(j + (flag2 ? 1 : 0)), Pair.of(parameterAnnotations[j - k], parameterTypes[j - k]));
paramMap.put(attr.variableName(j + (flag2 ? 1 : 0)), Pair.of(parameterAnnotations[j - k],
parameterTypes[j - k]));
}
} catch (NotFoundException e) {
e.printStackTrace();
@@ -214,7 +230,8 @@ public final class ReflectionUtil {
if (ctClass.isPrimitive() || "java.util.Date".equals(ctClass.getName())) {
return true;
}
return ctClass.getName().matches("^java\\.lang\\.((Boolean)|(Character)|(Byte)|(Short)|(Integer)|(Long)|(Float)|(Double)|(String))$");
return ctClass.getName().matches("^java\\.lang\\.((Boolean)|(Character)|(Byte)|(Short)|(Integer)|(Long)|" +
"(Float)|(Double)|(String))$");
}
/**
@@ -238,7 +255,8 @@ public final class ReflectionUtil {
* @throws InstantiationException InstantiationException
* @throws IllegalAccessException IllegalAccessException
*/
public static <T> T newWithNoParam(Class<T> handler) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
public static <T> T newWithNoParam(Class<T> handler) throws NoSuchMethodException, InvocationTargetException,
InstantiationException, IllegalAccessException {
return handler.getConstructor().newInstance();
}

View File

@@ -32,11 +32,11 @@ public class SharedDataUtil {
return (JsonObject) localMap.get(key);
}
public static JsonObject getJsonObjectForCustomConfig(String key) {
return getJsonConfig("customConfig").getJsonObject(key);
public static JsonObject getCustomConfig() {
return getJsonConfig("customConfig");
}
public static String getJsonStringForCustomConfig(String key) {
public static String getStringForCustomConfig(String key) {
return getJsonConfig("customConfig").getString(key);
}

View File

@@ -23,7 +23,6 @@ public class RouterVerticle extends AbstractVerticle {
private static final int port = SharedDataUtil.getValueForServerConfig("port");
private static final Router router = new RouterHandlerFactory(
SharedDataUtil.getJsonStringForCustomConfig("routerLocations"),
SharedDataUtil.getJsonStringForServerConfig("contextPath")).createRouter();
private static final JsonObject globalConfig = SharedDataUtil.getJsonConfig("globalConfig");

View File

@@ -3,7 +3,6 @@ package cn.qaiu.vx.core.verticle;
import cn.qaiu.vx.core.annotaions.Service;
import cn.qaiu.vx.core.base.BaseAsyncService;
import cn.qaiu.vx.core.util.ReflectionUtil;
import cn.qaiu.vx.core.util.SharedDataUtil;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.serviceproxy.ServiceBinder;
@@ -27,8 +26,7 @@ public class ServiceVerticle extends AbstractVerticle {
private static final Set<Class<?>> handlers;
static {
String handlerLocations = SharedDataUtil.getJsonStringForCustomConfig("handlerLocations");
Reflections reflections = ReflectionUtil.getReflections(handlerLocations);
Reflections reflections = ReflectionUtil.getReflections();
handlers = reflections.getTypesAnnotatedWith(Service.class);
}

View File

@@ -21,3 +21,5 @@ pnpm-debug.log*
*.njsproj
*.sln
*.sw?
/nfd-front.zip
/nfd-front

View File

@@ -1,5 +1,7 @@
# nfd-web
当前页面修改自开源项目 https://github.com/HurryBy/CloudDiskAnalysis
![11115](https://bd2.qaiu.cn/blog/11115.png)
## Project setup
```
npm install

View File

@@ -1,170 +1,168 @@
<!DOCTYPE html>
<html lang="zh-CN">
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Netdisk fast download</title>
<meta name="keywords"
content="">
<meta name="description"
content="">
<style>
.page-loading-wrap {
padding: 120px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Netdisk fast download</title>
<meta name="keywords"
content="Netdisk fast download,网盘直链解析工具">
<meta name="description"
content="Netdisk fast download 网盘直链解析工具">
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
<script>LA.init({id:"K8zkCkZMgFA6ShZK",ck:"K8zkCkZMgFA6ShZK"})</script>
.la-timer,
.la-timer>div {
position: relative;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
<style>
.page-loading-wrap {
padding: 120px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.la-timer {
display: block;
font-size: 0;
color: #fff;
}
.la-timer,
.la-timer>div {
position: relative;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.la-timer.la-dark {
color: #333;
}
.la-timer {
display: block;
font-size: 0;
color: #fff;
}
.la-timer>div {
display: inline-block;
float: none;
background-color: currentColor;
border: 0 solid currentColor;
}
.la-timer.la-dark {
color: #333;
}
.la-timer {
width: 32px;
height: 32px;
}
.la-timer>div {
display: inline-block;
float: none;
background-color: currentColor;
border: 0 solid currentColor;
}
.la-timer>div {
width: 32px;
height: 32px;
background: transparent;
border-width: 2px;
border-radius: 100%;
}
.la-timer {
width: 32px;
height: 32px;
}
.la-timer>div:before,
.la-timer>div:after {
position: absolute;
top: 14px;
left: 14px;
display: block;
width: 2px;
margin-top: -1px;
margin-left: -1px;
content: "";
background: currentColor;
border-radius: 2px;
-webkit-transform-origin: 1px 1px 0;
-moz-transform-origin: 1px 1px 0;
-ms-transform-origin: 1px 1px 0;
-o-transform-origin: 1px 1px 0;
transform-origin: 1px 1px 0;
-webkit-animation: timer-loader 1250ms infinite linear;
-moz-animation: timer-loader 1250ms infinite linear;
-o-animation: timer-loader 1250ms infinite linear;
animation: timer-loader 1250ms infinite linear;
-webkit-animation-delay: -625ms;
-moz-animation-delay: -625ms;
-o-animation-delay: -625ms;
animation-delay: -625ms;
}
.la-timer>div {
width: 32px;
height: 32px;
background: transparent;
border-width: 2px;
border-radius: 100%;
}
.la-timer>div:before {
height: 12px;
}
.la-timer>div:before,
.la-timer>div:after {
position: absolute;
top: 14px;
left: 14px;
display: block;
width: 2px;
margin-top: -1px;
margin-left: -1px;
content: "";
background: currentColor;
border-radius: 2px;
-webkit-transform-origin: 1px 1px 0;
-moz-transform-origin: 1px 1px 0;
-ms-transform-origin: 1px 1px 0;
-o-transform-origin: 1px 1px 0;
transform-origin: 1px 1px 0;
-webkit-animation: timer-loader 1250ms infinite linear;
-moz-animation: timer-loader 1250ms infinite linear;
-o-animation: timer-loader 1250ms infinite linear;
animation: timer-loader 1250ms infinite linear;
-webkit-animation-delay: -625ms;
-moz-animation-delay: -625ms;
-o-animation-delay: -625ms;
animation-delay: -625ms;
}
.la-timer>div:after {
height: 8px;
-webkit-animation-duration: 15s;
-moz-animation-duration: 15s;
-o-animation-duration: 15s;
animation-duration: 15s;
-webkit-animation-delay: -7.5s;
-moz-animation-delay: -7.5s;
-o-animation-delay: -7.5s;
animation-delay: -7.5s;
}
.la-timer>div:before {
height: 12px;
}
@-webkit-keyframes timer-loader {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
.la-timer>div:after {
height: 8px;
-webkit-animation-duration: 15s;
-moz-animation-duration: 15s;
-o-animation-duration: 15s;
animation-duration: 15s;
-webkit-animation-delay: -7.5s;
-moz-animation-delay: -7.5s;
-o-animation-delay: -7.5s;
animation-delay: -7.5s;
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes timer-loader {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
@-moz-keyframes timer-loader {
0% {
-moz-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-moz-keyframes timer-loader {
0% {
-moz-transform: rotate(0deg);
transform: rotate(0deg);
}
@-o-keyframes timer-loader {
0% {
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg);
}
}
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-o-keyframes timer-loader {
0% {
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
@keyframes timer-loader {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes timer-loader {
0% {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
</style>
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div id="app">
<div class="page-loading-wrap">
<div style="color: #4e9ff5" class="la-timer">
<div></div>
</div>
<h4 style="margin-top:20px;font-size:14px;font-weight:400;color: #515a6e;">正在加载资源...</h4>
<div class="page-loading-wrap">
<div style="color: #4e9ff5" class="la-timer">
<div></div>
</div>
<h4 style="margin-top:20px;font-size:14px;font-weight:400;color: #515a6e;">正在加载资源...</h4>
</div>
</div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -9,8 +9,8 @@
</div>
<h3 style="text-align: center;">NFD网盘直链解析(API演示)</h3>
<div class="typo">
<p><strong>项目地址 </strong><a href="https://github.com/qaiu/netdisk-fast-download" target="_blank"
rel="nofollow"><u>点我跳转</u></a></p>
<p><strong>项目GitHub </strong><a href="https://github.com/qaiu/netdisk-fast-download" target="_blank"
rel="nofollow"><u>netdisk-fast-download</u></a></p>
<p><strong>当前页面修改自开源项目</strong><a href="https://github.com/HurryBy/CloudDiskAnalysis" target="_blank"
rel="nofollow"><u>CloudDiskAnalysis</u></a></p>
<p><strong>目前支持 </strong>已支持蓝奏云/奶牛快传/移动云云空间/UC网盘(暂时失效)/小飞机盘/亿方云/123云盘</p>

View File

@@ -1,9 +1,5 @@
const { defineConfig } = require('@vue/cli-service')
const path = require("path");
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false
})
function resolve(dir) {
return path.join(__dirname, dir)
@@ -12,6 +8,8 @@ const CompressionPlugin = require('compression-webpack-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin')
module.exports = {
transpileDependencies: true,
lintOnSave: false,
outputDir: 'nfd-front',
devServer: {
host: '127.0.0.1',

View File

@@ -2,15 +2,12 @@ package cn.qaiu.lz.common.interceptorImpl;
import cn.qaiu.vx.core.base.BaseHttpApi;
import cn.qaiu.vx.core.interceptor.Interceptor;
import cn.qaiu.vx.core.model.JsonResult;
import cn.qaiu.vx.core.util.CommonUtil;
import cn.qaiu.vx.core.util.SharedDataUtil;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.json.JsonArray;
import io.vertx.core.shareddata.LocalMap;
import io.vertx.ext.web.RoutingContext;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import static cn.qaiu.vx.core.util.ConfigConstant.IGNORES_REG;
/**
* 默认拦截器实现
@@ -20,10 +17,16 @@ import lombok.val;
@Slf4j
public class DefaultInterceptor implements Interceptor, BaseHttpApi {
private final JsonArray ignores = SharedDataUtil.getJsonArrayForCustomConfig("ignoresReg");
protected final JsonArray ignores = SharedDataUtil.getJsonArrayForCustomConfig(IGNORES_REG);
@Override
public void handle(RoutingContext ctx) {
public void beforeHandle(RoutingContext ctx) {
ctx.next();
}
@Override
public void afterHandle(RoutingContext ctx) {
}
}

View File

@@ -0,0 +1,23 @@
package cn.qaiu.lz.common.model;
import cn.qaiu.lz.common.util.SnowflakeIdWorker;
import lombok.Data;
import java.util.Date;
@Data
abstract public class BaseModel {
public static final long serialVersionUID = 1L;
private String id = String.valueOf(SnowflakeIdWorker.idWorker().nextId());
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
}

View File

@@ -0,0 +1,16 @@
package cn.qaiu.lz.common.model;
import io.vertx.core.MultiMap;
public class FileInfo extends BaseModel {
private String fileName;
private String fileType;
private Long fileSize;
private String download;
private MultiMap header;
}

View File

@@ -0,0 +1,5 @@
package cn.qaiu.lz.common.model;
public class ParserInfo {
}

View File

@@ -4,42 +4,42 @@ import cn.qaiu.lz.common.parser.impl.*;
import io.vertx.core.Future;
public interface IPanTool {
Future<String> parse(String data, String code);
Future<String> parse();
static IPanTool typeMatching(String type) {
static IPanTool typeMatching(String type, String key, String pwd) {
return switch (type) {
case "lz" -> new LzTool();
case "cow" -> new CowTool();
case "ec" -> new EcTool();
case "fc" -> new FcTool();
case "uc" -> new UcTool();
case "ye" -> new YeTool();
case "fj" -> new FjTool();
case "lz" -> new LzTool(key, pwd);
case "cow" -> new CowTool(key, pwd);
case "ec" -> new EcTool(key, pwd);
case "fc" -> new FcTool(key, pwd);
case "uc" -> new UcTool(key, pwd);
case "ye" -> new YeTool(key, pwd);
case "fj" -> new FjTool(key, pwd);
default -> {
throw new IllegalArgumentException("未知分享类型");
throw new UnsupportedOperationException("未知分享类型");
}
};
}
static IPanTool shareURLPrefixMatching(String url) {
static IPanTool shareURLPrefixMatching(String url, String pwd) {
if (url.startsWith(CowTool.SHARE_URL_PREFIX)) {
return new CowTool();
if (url.contains(CowTool.LINK_KEY)) {
return new CowTool(url, pwd);
} else if (url.startsWith(EcTool.SHARE_URL_PREFIX)) {
return new EcTool();
return new EcTool(url, pwd);
} else if (url.startsWith(FcTool.SHARE_URL_PREFIX0)) {
return new FcTool();
return new FcTool(url, pwd);
} else if (url.startsWith(UcTool.SHARE_URL_PREFIX)) {
return new UcTool();
return new UcTool(url, pwd);
} else if (url.startsWith(YeTool.SHARE_URL_PREFIX)) {
return new YeTool();
return new YeTool(url, pwd);
} else if (url.startsWith(FjTool.SHARE_URL_PREFIX)) {
return new FjTool();
} else if (url.contains("lanzou")) {
return new LzTool();
return new FjTool(url, pwd);
} else if (url.contains(LzTool.LINK_KEY)) {
return new LzTool(url, pwd);
}
throw new IllegalArgumentException("未知分享类型");
throw new UnsupportedOperationException("未知分享类型");
}
}

View File

@@ -0,0 +1,57 @@
package cn.qaiu.lz.common.parser;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class PanBase {
protected Logger log = LoggerFactory.getLogger(this.getClass());
protected Promise<String> promise = Promise.promise();
protected WebClient client = WebClient.create(VertxHolder.getVertxInstance());
protected WebClient clientNoRedirects = WebClient.create(VertxHolder.getVertxInstance(), OPTIONS);
private static final WebClientOptions OPTIONS = new WebClientOptions().setFollowRedirects(false);
protected String key;
protected String pwd;
protected PanBase(String key, String pwd) {
this.key = key;
this.pwd = pwd;
}
protected void fail(Throwable t, String errorMsg, Object... args) {
try {
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
log.error("解析异常: " + s, t.fillInStackTrace());
promise.fail(this.getClass().getSimpleName() + ": 解析异常: " + s + " -> " + t);
} catch (Exception e) {
log.error("ErrorMsg format fail. The parameter has been discarded", e);
log.error("解析异常: " + errorMsg, t.fillInStackTrace());
promise.fail(this.getClass().getSimpleName() + ": 解析异常: " + errorMsg + " -> " + t);
}
}
protected void fail(String errorMsg, Object... args) {
try {
String s = String.format(errorMsg.replaceAll("\\{}", "%s"), args);
log.error("解析异常: " + s);
promise.fail(this.getClass().getSimpleName() + " - 解析异常: " + s);
} catch (Exception e) {
log.error("ErrorMsg format fail. The parameter has been discarded", e);
log.error("解析异常: " + errorMsg);
promise.fail(this.getClass().getSimpleName() + " - 解析异常: " + errorMsg);
}
}
protected Handler<Throwable> handleFail(String errorMsg) {
return t -> fail(this.getClass().getSimpleName() + " - 请求异常 {}: -> {}", errorMsg, t.fillInStackTrace());
}
}

View File

@@ -1,14 +1,10 @@
package cn.qaiu.lz.common.parser.impl;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.parser.PanBase;
import cn.qaiu.lz.common.util.CommonUtils;
import cn.qaiu.lz.common.util.PanExceptionUtils;
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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
/**
@@ -17,23 +13,35 @@ import org.apache.commons.lang3.StringUtils;
* @author <a href="https://qaiu.top">QAIU</a>
* @date 2023/4/21 21:19
*/
@Slf4j
public class CowTool implements IPanTool {
public class CowTool extends PanBase implements IPanTool {
private static final String API_REQUEST_URL = "https://cowtransfer.com/core/api/transfer/share";
public static final String SHARE_URL_PREFIX = "https://cowtransfer.com/s/";
public Future<String> parse(String data, String code) {
Promise<String> promise = Promise.promise();
WebClient client = WebClient.create(VertxHolder.getVertxInstance());
String key = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data);
client.getAbs(API_REQUEST_URL + "?uniqueUrl=" + key).send().onSuccess(res -> {
public static final String LINK_KEY = "cowtransfer.com/s/";
public CowTool(String key, String pwd) {
super(key, pwd);
}
public Future<String> parse() {
key = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key);
String url = API_REQUEST_URL + "?uniqueUrl=" + key;
client.getAbs(url).send().onSuccess(res -> {
JsonObject resJson = res.bodyAsJsonObject();
if ("success".equals(resJson.getString("message")) && resJson.containsKey("data")) {
JsonObject dataJson = resJson.getJsonObject("data");
String guid = dataJson.getString("guid");
String fileId = dataJson.getJsonObject("firstFile").getString("id");
String url2 = API_REQUEST_URL + "/download?transferGuid=" + guid + "&fileId=" + fileId;
StringBuilder url2Build = new StringBuilder(API_REQUEST_URL + "/download?transferGuid=" + guid);
if (dataJson.getBoolean("zipDownload")) {
// &title=xxx
JsonObject firstFolder = dataJson.getJsonObject("firstFolder");
url2Build.append("&title=").append(firstFolder.getString("title"));
} else {
String fileId = dataJson.getJsonObject("firstFile").getString("id");
url2Build.append("&fileId=").append(fileId);
}
String url2 = url2Build.toString();
client.getAbs(url2).send().onSuccess(res2 -> {
JsonObject res2Json = res2.bodyAsJsonObject();
if ("success".equals(res2Json.getString("message")) && res2Json.containsKey("data")) {
@@ -44,19 +52,15 @@ public class CowTool implements IPanTool {
promise.complete(downloadUrl);
return;
}
log.error("cow parse fail: {}; downloadUrl is empty", url2);
promise.fail("cow parse fail: " + url2 + "; downloadUrl is empty");
fail("cow parse fail: {}; downloadUrl is empty", url2);
return;
}
log.error("cow parse fail: {}; json: {}", url2, res2Json);
promise.fail("cow parse fail: " + url2 + "; json:" + res2Json);
});
fail("cow parse fail: {}; json: {}", url2, res2Json);
}).onFailure(handleFail(url2));
return;
}
log.error("cow parse fail: {}; json: {}", key, resJson);
promise.fail("cow parse fail: " + key + "; json:" + resJson);
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Cow", key, t)));
fail("cow parse fail: {}; json: {}", key, resJson);
}).onFailure(handleFail(url));
return promise.future();
}

View File

@@ -1,22 +1,17 @@
package cn.qaiu.lz.common.parser.impl;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.parser.PanBase;
import cn.qaiu.lz.common.util.CommonUtils;
import cn.qaiu.lz.common.util.PanExceptionUtils;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClient;
import io.vertx.uritemplate.UriTemplate;
import lombok.extern.slf4j.Slf4j;
/**
* 移动云空间解析
*/
@Slf4j
public class EcTool implements IPanTool {
public class EcTool extends PanBase implements IPanTool {
private static final String FIRST_REQUEST_URL = "https://www.ecpan.cn/drive/fileextoverrid" +
".do?chainUrlTemplate=https:%2F%2Fwww.ecpan" +
".cn%2Fweb%2F%23%2FyunpanProxy%3Fpath%3D%252F%2523%252Fdrive%252Foutside&parentId=-1&data={dataKey}";
@@ -25,10 +20,12 @@ public class EcTool implements IPanTool {
public static final String SHARE_URL_PREFIX = "www.ecpan.cn/";
public Future<String> parse(String data, String code) {
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data);
Promise<String> promise = Promise.promise();
WebClient client = WebClient.create(VertxHolder.getVertxInstance());
public EcTool(String key, String pwd) {
super(key, pwd);
}
public Future<String> parse() {
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key);
// 第一次请求 获取文件信息
client.getAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("dataKey", dataKey).send().onSuccess(res -> {
JsonObject jsonObject = res.bodyAsJsonObject();
@@ -37,8 +34,7 @@ public class EcTool implements IPanTool {
.getJsonObject("var")
.getJsonObject("chainFileInfo");
if (fileInfo.containsKey("errMesg")) {
promise.fail(new RuntimeException(DOWNLOAD_REQUEST_URL + " 解析失败: "
+ fileInfo.getString("errMesg")) + " key = " + dataKey);
fail("{} 解析失败:{} key = {}", FIRST_REQUEST_URL, fileInfo.getString("errMesg"), dataKey);
return;
}
JsonObject cloudpFile = fileInfo.getJsonObject("cloudpFile");
@@ -55,9 +51,9 @@ public class EcTool implements IPanTool {
JsonObject jsonRes = res2.bodyAsJsonObject();
log.debug("ecPan get download url -> {}", res2.body().toString());
promise.complete(jsonRes.getJsonObject("var").getString("downloadUrl"));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ec", dataKey, t)));
}).onFailure(handleFail(""));
}
).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ec", dataKey, t)));;
).onFailure(handleFail(FIRST_REQUEST_URL));
return promise.future();
}
}

View File

@@ -1,18 +1,14 @@
package cn.qaiu.lz.common.parser.impl;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.parser.PanBase;
import cn.qaiu.lz.common.util.CommonUtils;
import cn.qaiu.lz.common.util.PanExceptionUtils;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.Future;
import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.ext.web.client.WebClientSession;
import io.vertx.uritemplate.UriTemplate;
import org.apache.commons.lang3.StringUtils;
@@ -23,7 +19,7 @@ import java.util.regex.Pattern;
/**
* 360亿方云
*/
public class FcTool implements IPanTool {
public class FcTool extends PanBase implements IPanTool {
public static final String SHARE_URL_PREFIX0 = "https://v2.fangcloud.com/s";
public static final String SHARE_URL_PREFIX = "https://v2.fangcloud.com/sharing/";
@@ -31,45 +27,44 @@ public class FcTool implements IPanTool {
private static final String DOWN_REQUEST_URL = "https://v2.fangcloud.cn/apps/files/download?file_id={fid}" +
"&scenario=share&unique_name={uname}";
public Future<String> parse(String data, String code) {
data = data.replace("share","sharing");
public FcTool(String key, String pwd) {
super(key, pwd);
}
public Future<String> parse() {
String data = key.replace("share","sharing");
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data);
Promise<String> promise = Promise.promise();
Vertx vertx = VertxHolder.getVertxInstance();
WebClient client = WebClient.create(vertx);
WebClientSession sClient = WebClientSession.create(client);
// 第一次请求 自动重定向
sClient.getAbs(SHARE_URL_PREFIX + dataKey).send().onSuccess(res -> {
// 判断是否是加密分享
if (StringUtils.isNotEmpty(code)) {
if (StringUtils.isNotEmpty(pwd)) {
// 获取requesttoken
String html = res.bodyAsString();
Pattern compile = Pattern.compile("name=\"requesttoken\"\\s+value=\"([a-zA-Z0-9_+=]+)\"");
Matcher matcher = compile.matcher(html);
if (!matcher.find()) {
promise.fail(SHARE_URL_PREFIX + " 未匹配到加密分享的密码输入页面的requesttoken: \n" + html);
fail(SHARE_URL_PREFIX + " 未匹配到加密分享的密码输入页面的requesttoken");
return;
}
String token = matcher.group(1);
sClient.postAbs(SHARE_URL_PREFIX2 + dataKey).sendForm(MultiMap.caseInsensitiveMultiMap()
.set("requesttoken", token)
.set("password", code)).onSuccess(res2 -> {
.set("password", pwd)).onSuccess(res2 -> {
if (res2.statusCode() == 302) {
sClient.getAbs(res2.getHeader("Location")).send().onSuccess(res3 ->
getDownURL(dataKey, promise, res3, sClient))
.onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Fc", dataKey, t)));
sClient.getAbs(res2.getHeader("Location")).send()
.onSuccess(res3 -> getDownURL(dataKey, promise, res3, sClient))
.onFailure(handleFail(res2.getHeader("Location")));
return;
}
promise.fail(SHARE_URL_PREFIX + " 密码跳转后获取重定向失败 \n" + html);
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Fc", dataKey, t)));
fail(SHARE_URL_PREFIX + " 密码跳转后获取重定向失败");
}).onFailure(handleFail(SHARE_URL_PREFIX2));
return;
}
getDownURL(dataKey, promise, res, sClient);
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Fc", dataKey, t)));
}).onFailure(handleFail(SHARE_URL_PREFIX + dataKey));
return promise.future();
}
@@ -80,14 +75,12 @@ public class FcTool implements IPanTool {
Pattern compile = Pattern.compile("id=\"typed_id\"\\s+value=\"file_(\\d+)\"");
Matcher matcher = compile.matcher(html);
if (!matcher.find()) {
promise.fail(SHARE_URL_PREFIX + " 未匹配到文件id(typed_id): \n" + html);
fail(SHARE_URL_PREFIX + " 未匹配到文件id(typed_id)");
return;
}
String fid = matcher.group(1);
// 创建一个不自动重定向的WebClientSession
WebClient clientNoRedirects = WebClient.create(VertxHolder.getVertxInstance(),
new WebClientOptions().setFollowRedirects(false));
WebClientSession sClientNoRedirects = WebClientSession.create(clientNoRedirects, sClient.cookieStore());
// 第二次请求
sClientNoRedirects.getAbs(UriTemplate.of(DOWN_REQUEST_URL))
@@ -97,14 +90,14 @@ public class FcTool implements IPanTool {
try {
resJson = res2.bodyAsJsonObject();
} catch (Exception e) {
promise.fail(DOWN_REQUEST_URL + " 第二次请求没有返回JSON, 可能下载受限: " + res2.bodyAsString());
fail(e, DOWN_REQUEST_URL + " 第二次请求没有返回JSON, 可能下载受限");
return;
}
if (!resJson.getBoolean("success")) {
promise.fail(DOWN_REQUEST_URL + " 第二次请求未得到正确相应: " + resJson);
fail(DOWN_REQUEST_URL + " 第二次请求未得到正确相应: " + resJson);
return;
}
promise.complete(resJson.getString("download_url"));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Fc", dataKey, t)));
}).onFailure(handleFail(DOWN_REQUEST_URL));
}
}

View File

@@ -1,13 +1,12 @@
package cn.qaiu.lz.common.parser.impl;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.parser.PanBase;
import cn.qaiu.lz.common.util.AESUtils;
import cn.qaiu.lz.common.util.CommonUtils;
import cn.qaiu.lz.common.util.PanExceptionUtils;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.Future;
import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
@@ -20,7 +19,7 @@ import java.util.UUID;
*
* @version V016_230609
*/
public class FjTool implements IPanTool {
public class FjTool extends PanBase implements IPanTool {
public static final String SHARE_URL_PREFIX = "https://www.feijix.com/s/";
private static final String API_URL_PREFIX = "https://api.feijipan.com/ws/";
@@ -31,10 +30,13 @@ public class FjTool implements IPanTool {
private static final String SECOND_REQUEST_URL = API_URL_PREFIX + "file/redirect?downloadId={fidEncode}&enable=1" +
"&devType=6&uuid={uuid}&timestamp={ts}&auth={auth}";
public Future<String> parse(String data, String code) {
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data);
public FjTool(String key, String pwd) {
super(key, pwd);
}
public Future<String> parse() {
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key);
Promise<String> promise = Promise.promise();
WebClient client = WebClient.create(VertxHolder.getVertxInstance(),
new WebClientOptions().setFollowRedirects(false));
String shareId = String.valueOf(AESUtils.idEncrypt(dataKey));
@@ -44,11 +46,11 @@ public class FjTool implements IPanTool {
client.postAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("shareId", shareId).send().onSuccess(res -> {
JsonObject resJson = res.bodyAsJsonObject();
if (resJson.getInteger("code") != 200) {
promise.fail(FIRST_REQUEST_URL + " 返回异常: " + resJson);
fail(FIRST_REQUEST_URL + " 返回异常: " + resJson);
return;
}
if (resJson.getJsonArray("list").size() == 0) {
promise.fail(FIRST_REQUEST_URL + " 解析文件列表为空: " + resJson);
fail(FIRST_REQUEST_URL + " 解析文件列表为空: " + resJson);
return;
}
// 文件Id
@@ -67,12 +69,12 @@ public class FjTool implements IPanTool {
.setTemplateParam("auth", auth).send().onSuccess(res2 -> {
MultiMap headers = res2.headers();
if (!headers.contains("Location")) {
promise.fail(SECOND_REQUEST_URL + " 未找到重定向URL: \n" + res.headers());
fail(SECOND_REQUEST_URL + " 未找到重定向URL: \n" + res.headers());
return;
}
promise.complete(headers.get("Location"));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Fj", dataKey, t)));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Fj", dataKey, t)));
}).onFailure(handleFail(SECOND_REQUEST_URL));
}).onFailure(handleFail(FIRST_REQUEST_URL));
return promise.future();
}

View File

@@ -1,7 +1,8 @@
package cn.qaiu.lz.common.parser.impl;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.util.PanExceptionUtils;
import cn.qaiu.lz.common.parser.PanBase;
import cn.qaiu.lz.common.util.JsExecUtils;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.Future;
import io.vertx.core.MultiMap;
@@ -9,7 +10,10 @@ import io.vertx.core.Promise;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
import javax.script.ScriptException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -19,50 +23,123 @@ import java.util.regex.Pattern;
* @author QAIU
* @version 1.0 update 2021/5/16 10:39
*/
public class LzTool implements IPanTool {
public class LzTool extends PanBase implements IPanTool {
public static final String SHARE_URL_PREFIX = "https://wwwa.lanzoui.com";
public Future<String> parse(String data, String code) {
Promise<String> promise = Promise.promise();
String key = data.indexOf('/') > 0 ? data : SHARE_URL_PREFIX + "/" + data;
public static final String LINK_KEY = "lanzou";
public LzTool(String key, String pwd) {
super(key, pwd);
}
/*
var wsk_sign = 'c20230818';
var aihidcms = 'Fn5L';
var iucjdsd = '';
var ws_sign = 'c20230818';
var sasign = 'B2EBPw8_bBDVRWFdoAzMGOlI5ATwEbVFgV2NVZwVhATYILld0WjoAZQhoVDsEYlZjBm4BNgVoVGcHMQ_c_c';
var ajaxdata = '?ctdf';
$.ajax({
type : 'post',
url : '/ajaxm.php',
//b data : { 'action':'downprocess','signs':ajaxdata,'sign':'w},
data : { 'action':'downprocess','signs':ajaxdata,'sign':sasign,'websign':iucjdsd,'websignkey':aihidcms,'ves':1 },
//b data : { 'action':'downprocess','signs':ajaxdata,'sign':'','websign':ws_sign,'websignkey':wsk_sign,'ves':1 },
dataType : 'json',
success:function(msg){
var date = msg;
if(date.zt == '1'){
$("#tourl").html("<a href="+date.dom+"/file/"+ date.url +" target=_blank rel=noreferrer><span class=txt>电信下载</span><span class='txt txtc'>联通下载</span><span class=txt>普通下载</span></a>");
setTimeout('$("#outime").css("display","block");',1800000);
}else{
$("#tourl").html("网页超时,请刷新");
};
},
error:function(){
$("#tourl").html("获取失败,请刷新");
}
});
*/
/**
* 蓝奏云解析器
*
* @return url String
*/
@SuppressWarnings("unchecked")
public Future<String> parse() {
String sUrl = key.startsWith("https://") ? key : SHARE_URL_PREFIX + "/" + key;
WebClient client = WebClient.create(VertxHolder.getVertxInstance(),
new WebClientOptions().setFollowRedirects(false));
client.getAbs(key).send().onSuccess(res -> {
client.getAbs(sUrl).send().onSuccess(res -> {
String html = res.bodyAsString();
// 匹配iframe
Pattern compile = Pattern.compile("src=\"(/fn\\?[a-zA-Z\\d_+/=]{16,})\"");
Matcher matcher = compile.matcher(html);
// 没有Iframe说明是加密分享, 匹配sign通过密码请求下载页面
if (!matcher.find()) {
// 没有Iframe说明是加密分享, 匹配sign通过密码请求下载页面
Pattern compile2 = Pattern.compile("sign=(\\w{16,})");
Matcher matcher2 = compile2.matcher(html);
if (!matcher2.find()) {
promise.fail(key + ": sign正则匹配失败, 可能分享已失效: " + html);
// 处理一下JS
String jsText = getJsText(html);
if (jsText == null) {
fail(SHARE_URL_PREFIX + " -> " + sUrl + ": js脚本匹配失败, 可能分享已失效");
return;
}
jsText = jsText.replace("document.getElementById('pwd').value", "\"" + pwd + "\"");
jsText = jsText.substring(0, jsText.indexOf("document.getElementById('rpt')"));
try {
ScriptObjectMirror scriptObjectMirror = JsExecUtils.executeDynamicJs(jsText, "down_p");
getDownURL(promise, sUrl, client, (Map<String, String>) scriptObjectMirror.get("data"));
} catch (ScriptException | NoSuchMethodException e) {
fail(e, "js引擎执行失败");
return;
}
String sign = matcher2.group(1);
getDownURL(promise, code, key, client, sign);
return;
}
String iframePath = matcher.group(1);
client.getAbs(SHARE_URL_PREFIX + iframePath).send().onSuccess(res2 -> {
String html2 = res2.bodyAsString();
System.out.println(html);
Matcher matcher2 = Pattern.compile("'sign'\s*:\s*'(\\w+)'").matcher(html2);
if (!matcher2.find()) {
promise.fail(SHARE_URL_PREFIX + iframePath + " -> " + key + ": sign正则匹配失败, 可能分享已失效: " + html2);
// 去TMD正则
// Matcher matcher2 = Pattern.compile("'sign'\s*:\s*'(\\w+)'").matcher(html2);
String jsText = getJsText(html2);
if (jsText == null) {
fail(SHARE_URL_PREFIX + iframePath + " -> " + sUrl + ": js脚本匹配失败, 可能分享已失效");
return;
}
String sign = matcher2.group(1);
getDownURL(promise, code, key, client, sign);
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Lz", key, t)));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Lz", key, t)));
try {
ScriptObjectMirror scriptObjectMirror = JsExecUtils.executeDynamicJs(jsText, null);
getDownURL(promise, sUrl, client, (Map<String, String>) scriptObjectMirror.get("data"));
} catch (ScriptException | NoSuchMethodException e) {
fail(e, "js引擎执行失败");
}
}).onFailure(handleFail(SHARE_URL_PREFIX));
}).onFailure(handleFail(sUrl));
return promise.future();
}
private void getDownURL(Promise<String> promise, String code, String key, WebClient client, String sign) {
private String getJsText(String html) {
String jsTagStart = "<script type=\"text/javascript\">";
String jsTagEnd = "</script>";
int index = html.indexOf(jsTagStart);
if (index == -1) {
return null;
}
int startPos = index + jsTagStart.length();
int endPos = html.indexOf(jsTagEnd, startPos);
return html.substring(startPos, endPos);
}
private void getDownURL(Promise<String> promise, String key, WebClient client, Map<String, ?> signMap) {
MultiMap map = MultiMap.caseInsensitiveMultiMap();
signMap.forEach((k, v) -> {
map.set(k, v.toString());
});
MultiMap headers = MultiMap.caseInsensitiveMultiMap();
var userAgent2 = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, " +
"like " +
@@ -73,19 +150,19 @@ public class LzTool implements IPanTool {
headers.set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
headers.set("sec-ch-ua-mobile", "sec-ch-ua-mobile");
client.postAbs(SHARE_URL_PREFIX + "/ajaxm.php").putHeaders(headers).sendForm(MultiMap
String url = SHARE_URL_PREFIX + "/ajaxm.php";
client.postAbs(url).putHeaders(headers).sendForm(MultiMap
.caseInsensitiveMultiMap()
.set("action", "downprocess")
.set("sign", sign).set("p", code)).onSuccess(res2 -> {
.setAll(map)).onSuccess(res2 -> {
JsonObject urlJson = res2.bodyAsJsonObject();
if (urlJson.getInteger("zt") != 1) {
promise.fail(urlJson.getString("inf"));
fail(urlJson.getString("inf"));
return;
}
String downUrl = urlJson.getString("dom") + "/file/" + urlJson.getString("url");
client.getAbs(downUrl).putHeaders(headers).send()
.onSuccess(res3 -> promise.complete(res3.headers().get("Location")))
.onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Lz", key, t)));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Lz", key, t)));
.onFailure(handleFail(downUrl));
}).onFailure(handleFail(url));
}
}

View File

@@ -4,7 +4,7 @@ import io.vertx.core.Future;
import io.vertx.core.Promise;
public class QkTool {
public static Future<String> parse(String data, String code) {
public static Future<String> parse() {
Promise<String> promise = Promise.promise();
return promise.future();

View File

@@ -1,22 +1,17 @@
package cn.qaiu.lz.common.parser.impl;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.parser.PanBase;
import cn.qaiu.lz.common.util.CommonUtils;
import cn.qaiu.lz.common.util.PanExceptionUtils;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.WebClient;
import io.vertx.uritemplate.UriTemplate;
import lombok.extern.slf4j.Slf4j;
/**
* UC网盘解析
*/
@Slf4j
public class UcTool implements IPanTool {
public class UcTool extends PanBase implements IPanTool {
private static final String API_URL_PREFIX = "https://pc-api.uc.cn/1/clouddrive/";
public static final String SHARE_URL_PREFIX = "https://fast.uc.cn/s/";
@@ -29,11 +24,13 @@ public class UcTool implements IPanTool {
private static final String THIRD_REQUEST_URL = API_URL_PREFIX + "file/download?entry=ft&fr=pc&pr=UCBrowser";
public Future<String> parse(String data, String code) {
var dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data);
var passcode = (code == null) ? "" : code;
Promise<String> promise = Promise.promise();
var client = WebClient.create(VertxHolder.getVertxInstance());
public UcTool(String key, String pwd) {
super(key, pwd);
}
public Future<String> parse() {
var dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key);
var passcode = (pwd == null) ? "" : pwd;
var jsonObject = JsonObject.of("share_for_transfer", true);
jsonObject.put("pwd_id", dataKey);
jsonObject.put("passcode", passcode);
@@ -42,7 +39,7 @@ public class UcTool implements IPanTool {
log.debug("第一阶段 {}", res.body());
var resJson = res.bodyAsJsonObject();
if (resJson.getInteger("code") != 0) {
promise.fail(FIRST_REQUEST_URL + " 返回异常: " + resJson);
fail(FIRST_REQUEST_URL + " 返回异常: " + resJson);
return;
}
var stoken = resJson.getJsonObject("data").getString("stoken");
@@ -55,7 +52,7 @@ public class UcTool implements IPanTool {
log.debug("第二阶段 {}", res2.body());
JsonObject resJson2 = res2.bodyAsJsonObject();
if (resJson2.getInteger("code") != 0) {
promise.fail(FIRST_REQUEST_URL + " 返回异常: " + resJson2);
fail(FIRST_REQUEST_URL + " 返回异常: " + resJson2);
return;
}
// 文件信息
@@ -71,15 +68,15 @@ public class UcTool implements IPanTool {
log.debug("第三阶段 {}", res3.body());
var resJson3 = res3.bodyAsJsonObject();
if (resJson3.getInteger("code") != 0) {
promise.fail(FIRST_REQUEST_URL + " 返回异常: " + resJson2);
fail(FIRST_REQUEST_URL + " 返回异常: " + resJson2);
return;
}
promise.complete(resJson3.getJsonArray("data").getJsonObject(0).getString("download_url"));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Uc", dataKey, t)));
}).onFailure(handleFail(THIRD_REQUEST_URL));
}).onFailure(t -> promise.fail(new RuntimeException("解析异常: ", t.fillInStackTrace())));
}).onFailure(handleFail(SECOND_REQUEST_URL));
}
).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Uc", dataKey, t)));
).onFailure(handleFail(FIRST_REQUEST_URL));
return promise.future();
}
}

View File

@@ -1,22 +1,16 @@
package cn.qaiu.lz.common.parser.impl;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.parser.PanBase;
import cn.qaiu.lz.common.util.CommonUtils;
import cn.qaiu.lz.common.util.JsExecUtils;
import cn.qaiu.lz.common.util.PanExceptionUtils;
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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
import javax.script.ScriptException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Base64;
import java.util.Map;
@@ -26,30 +20,23 @@ import java.util.regex.Pattern;
/**
* 123网盘
*/
@Slf4j
public class YeTool implements IPanTool {
public class YeTool extends PanBase implements IPanTool {
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";
private static final String GET_FILE_INFO_URL="https://www.123pan
.com/b/api/share/get?limit=100&next=1&orderBy=file_name&orderDirection=asc" +
"&shareKey={shareKey}&SharePwd={pwd}&ParentFileId=0&Page=1&event=homeListFile&operateType=1&auth-key
={authKey}";
*/
private static final String GET_FILE_INFO_URL = "https://www.123pan.com/b/api/share/get?limit=100&next=1&orderBy" +
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";
private static final String DOWNLOAD_API_URL = "https://www.123pan.com/b/api/share/download/info?{authK}={authV}";
private static final String DOWNLOAD_API_URL = "https://www.123pan.com/a/api/share/download/info?{authK}={authV}";
public Future<String> parse(String data, String code) {
public YeTool(String key, String pwd) {
super(key, pwd);
}
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, data);
Promise<String> promise = Promise.promise();
WebClient client = WebClient.create(VertxHolder.getVertxInstance());
public Future<String> parse() {
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key);
client.getAbs(UriTemplate.of(FIRST_REQUEST_URL)).setTemplateParam("key", dataKey).send().onSuccess(res -> {
@@ -58,7 +45,7 @@ public class YeTool implements IPanTool {
Matcher matcher = compile.matcher(html);
if (!matcher.find()) {
promise.fail(html + "\n Ye: " + dataKey + " 正则匹配失败");
fail(html + "\n Ye: " + dataKey + " 正则匹配失败");
return;
}
String fileInfoString = matcher.group(1);
@@ -67,45 +54,45 @@ public class YeTool implements IPanTool {
JsonObject resListJson = fileInfoJson.getJsonObject("reslist");
if (resJson == null || resJson.getInteger("code") != 0) {
promise.fail(dataKey + " 解析到异常JSON: " + resJson);
fail(dataKey + " 解析到异常JSON: " + resJson);
return;
}
String shareKey = resJson.getJsonObject("data").getString("ShareKey");
if (resListJson == null || resListJson.getInteger("code") != 0) {
// 加密分享
if (StringUtils.isNotEmpty(code)) {
if (StringUtils.isNotEmpty(pwd)) {
client.getAbs(UriTemplate.of(GET_FILE_INFO_URL))
.setTemplateParam("shareKey", shareKey)
.setTemplateParam("pwd", code)
// .setTemplateParam("authKey", AESUtils.getAuthKey("/b/api/share/get"))
.setTemplateParam("pwd", pwd)
// .setTemplateParam("authKey", AESUtils.getAuthKey("/a/api/share/get"))
.putHeader("Platform", "web")
.putHeader("App-Version", "3")
.send().onSuccess(res2 -> {
JsonObject infoJson = res2.bodyAsJsonObject();
if (infoJson.getInteger("code") != 0) {
promise.fail("Ye: " + dataKey + " 状态码异常" + infoJson);
fail("{} 状态码异常 {}", dataKey, infoJson);
return;
}
JsonObject getFileInfoJson =
infoJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0);
getFileInfoJson.put("ShareKey", shareKey);
getDownUrl(promise, client, getFileInfoJson);
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye", dataKey, t)));
getDownUrl(client, getFileInfoJson);
}).onFailure(this.handleFail(GET_FILE_INFO_URL));
} else {
promise.fail(dataKey + " 该分享需要密码");
fail("该分享[{}]需要密码",dataKey);
}
return;
}
JsonObject reqBodyJson = resListJson.getJsonObject("data").getJsonArray("InfoList").getJsonObject(0);
reqBodyJson.put("ShareKey", shareKey);
getDownUrl(promise, client, reqBodyJson);
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye", dataKey, t)));
getDownUrl(client, reqBodyJson);
}).onFailure(this.handleFail(FIRST_REQUEST_URL));
return promise.future();
}
private static void getDownUrl(Promise<String> promise, WebClient client, JsonObject reqBodyJson) {
private void getDownUrl(WebClient client, JsonObject reqBodyJson) {
log.info(reqBodyJson.encodePrettily());
JsonObject jsonObject = new JsonObject();
// {"ShareKey":"iaKtVv-6OECd","FileID":2193732,"S3keyFlag":"1811834632-0","Size":4203111,
@@ -119,13 +106,9 @@ public class YeTool implements IPanTool {
// 调用JS文件获取签名
ScriptObjectMirror getSign;
try {
getSign = JsExecUtils.executeJs("getSign", "/b/api/share/download/info");
} catch (ScriptException | IOException | NoSuchMethodException e) {
promise.fail(e);
return;
}
if (getSign == null) {
promise.fail(ArrayUtils.toString(getSign));
getSign = JsExecUtils.executeJs("getSign", "/a/api/share/download/info");
} catch (Exception e) {
fail(e, "JS函数执行异常");
return;
}
log.info("ye getSign: {}={}", getSign.get("0").toString(), getSign.get("1").toString());
@@ -140,11 +123,11 @@ public class YeTool implements IPanTool {
try {
if (downURLJson.getInteger("code") != 0) {
promise.fail("Ye: downURLJson返回值异常->" + downURLJson);
fail("Ye: downURLJson返回值异常->" + downURLJson);
return;
}
} catch (Exception ignored) {
promise.fail("Ye: downURLJson格式异常->" + downURLJson);
fail("Ye: downURLJson格式异常->" + downURLJson);
return;
}
String downURL = downURLJson.getJsonObject("data").getString("DownloadURL");
@@ -159,23 +142,21 @@ public class YeTool implements IPanTool {
JsonObject res3Json = res3.bodyAsJsonObject();
try {
if (res3Json.getInteger("code") != 0) {
promise.fail("Ye: downUrl2返回值异常->" + res3Json);
fail("Ye: downUrl2返回值异常->" + res3Json);
return;
}
} catch (Exception ignored) {
promise.fail("Ye: downUrl2格式异常->" + downURLJson);
fail("Ye: downUrl2格式异常->" + downURLJson);
return;
}
promise.complete(res3Json.getJsonObject("data").getString("redirect_url"));
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye",
reqBodyJson.encodePrettily(), t)));
}).onFailure(this.handleFail("获取直链失败"));
} catch (MalformedURLException e) {
promise.fail("urlParams解析异常" + e.getMessage());
fail("urlParams解析异常" + e.getMessage());
}
}).onFailure(t -> promise.fail(PanExceptionUtils.fillRunTimeException("Ye",
reqBodyJson.encodePrettily(), t)));
}).onFailure(this.handleFail(DOWNLOAD_API_URL));
}
}

View File

@@ -8,12 +8,16 @@ import java.util.Map;
public class CommonUtils {
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);
}
String prefix = "https://";
if (!url.startsWith(urlPrefix) && url.startsWith(prefix)) {
urlPrefix = urlPrefix.substring(prefix.length());
return url.substring(url.indexOf(urlPrefix) + urlPrefix.length());
} else if (!url.startsWith(urlPrefix)) {
url = urlPrefix + url;
}
return url.substring(urlPrefix.length());
}

View File

@@ -1,5 +1,6 @@
package cn.qaiu.lz.common.util;
import org.apache.commons.lang3.StringUtils;
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
import javax.script.Invocable;
@@ -9,35 +10,80 @@ import javax.script.ScriptException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* 执行Js脚本
*
* @author <a href="https://qaiu.top">QAIU</a>
* @date 2023/7/29 17:35
*/
public class JsExecUtils {
private static final String JS_PATH = "/js/ye123.js";
private static final String JS_PATH = "js/ye123.js";
private static final String LZ_JS_PATH = "js/lz.js";
/**
* 调用js文件
*/
public static ScriptObjectMirror executeJs(String functionName, Object... args) throws ScriptException,
IOException, NoSuchMethodException {
private static final String RES_PATH;
private static final Invocable inv;
// 初始化脚本引擎
static {
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
//获取文件所在的相对路径
URL resource = JsExecUtils.class.getResource("/");
if (resource == null) {
throw new ScriptException("js resource path is null");
throw new RuntimeException("js resource path is null");
}
String path = resource.getPath();
String reader = path + JS_PATH;
FileReader fReader = new FileReader(reader);
engine.eval(fReader);
fReader.close();
RES_PATH = resource.getPath();
String reader = RES_PATH + JS_PATH;
try (FileReader fReader = new FileReader(reader)) {
engine.eval(fReader);
fReader.close();
inv = (Invocable) engine;
} catch (IOException | ScriptException e) {
throw new RuntimeException(e);
}
}
Invocable inv = (Invocable) engine;
//调用js中的方法
/**
* 调用js文件
*/
public static ScriptObjectMirror executeJs(String functionName, Object... args) throws ScriptException,
NoSuchMethodException {
//调用js中的函数
return (ScriptObjectMirror) inv.invokeFunction(functionName, args);
}
/**
* 调用执行蓝奏云js文件
*/
public static ScriptObjectMirror executeDynamicJs(String jsText, String funName) throws ScriptException,
NoSuchMethodException {
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
try {
//获取文件所在的相对路径
Path path;
try {
path = Paths.get(RES_PATH + LZ_JS_PATH);
} catch (RuntimeException ioe) {
path = Paths.get(RES_PATH.substring(1) + LZ_JS_PATH);
}
String jsContent = Files.readString(path) + "\n" + jsText;
engine.eval(jsContent);
Invocable inv = (Invocable) engine;
//调用js中的函数
if (StringUtils.isNotEmpty(funName)) {
inv.invokeFunction(funName);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return (ScriptObjectMirror) engine.get("signObj");
}
}

View File

@@ -1,4 +1,4 @@
package cn.qaiu.vx.core.util;
package cn.qaiu.lz.common.util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -30,6 +30,8 @@ public class SnowflakeIdWorker {
// ==============================Fields===========================================
//开始时间截 (2021-01-01)
private static final long EPOCH = 1609459200000L;
/**
* 机器id所占的位数
*/
@@ -133,9 +135,7 @@ public class SnowflakeIdWorker {
//时间截向左移22位(5+5+12)
long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
//开始时间截 (2021-01-01)
long twepoch = 1609459200000L;
return ((timestamp - twepoch) << timestampLeftShift) //
return ((timestamp - EPOCH) << timestampLeftShift) //
| (datacenterId << datacenterIdShift) //
| (workerId << sequenceBits) //
| sequence;
@@ -220,24 +220,4 @@ public class SnowflakeIdWorker {
}
return snowflakeIdWorkerCluster;
}
//==============================Test=============================================
/**
* 测试
*/
public static void main(String[] args) {
final SnowflakeIdWorker snowflakeIdWorkerCluster = idWorkerCluster(0, 1);
final SnowflakeIdWorker idWorker = idWorker();
for (int i = 0; i < 100; i++) {
long id = idWorker.nextId();
System.out.println(Long.toBinaryString(id));
System.out.println(id);
System.out.println("------------");
id = snowflakeIdWorkerCluster.nextId();
System.out.println(Long.toBinaryString(id));
System.out.println(id);
System.out.println("------------\n");
}
}
}

View File

@@ -1,7 +1,7 @@
package cn.qaiu.lz.web.http;
import cn.qaiu.lz.common.parser.IPanTool;
import cn.qaiu.lz.common.parser.impl.*;
import cn.qaiu.lz.common.parser.impl.EcTool;
import cn.qaiu.lz.web.model.SysUser;
import cn.qaiu.lz.web.service.UserService;
import cn.qaiu.vx.core.annotaions.RouteHandler;
@@ -43,7 +43,7 @@ public class ServerApi {
url = EcTool.SHARE_URL_PREFIX + request.getParam("data");
}
try {
IPanTool.shareURLPrefixMatching(url).parse(url, pwd).onSuccess(resUrl -> {
IPanTool.shareURLPrefixMatching(url, pwd).parse().onSuccess(resUrl -> {
response.putHeader("location", resUrl).setStatusCode(302).end();
promise.complete();
}).onFailure(t -> promise.fail(t.fillInStackTrace()));
@@ -54,12 +54,12 @@ public class ServerApi {
}
@RouteMapping(value = "/json/parser", method = RouteMethod.GET, order = 3)
public Future<String> parseJson(HttpServerResponse response, HttpServerRequest request, String url, String pwd) {
public Future<String> parseJson(HttpServerRequest request, String url, String pwd) {
if (url.contains(EcTool.SHARE_URL_PREFIX)) {
// 默认读取Url参数会被截断手动获取一下其他参数
url = EcTool.SHARE_URL_PREFIX + request.getParam("data");
}
return IPanTool.shareURLPrefixMatching(url).parse(url, pwd);
return IPanTool.shareURLPrefixMatching(url, pwd).parse();
}
@@ -72,7 +72,7 @@ public class ServerApi {
code = keys[1];
}
IPanTool.typeMatching(type).parse(key, code).onSuccess(resUrl -> response.putHeader("location", resUrl)
IPanTool.typeMatching(type, key, code).parse().onSuccess(resUrl -> response.putHeader("location", resUrl)
.setStatusCode(302).end()).onFailure(t -> {
response.putHeader(CONTENT_TYPE, "text/html;charset=utf-8");
response.end(t.getMessage());
@@ -80,13 +80,13 @@ public class ServerApi {
}
@RouteMapping(value = "/json/:type/:key", method = RouteMethod.GET, order = 2)
public Future<String> parseKeyJson(HttpServerResponse response, String type, String key) {
public Future<String> parseKeyJson(String type, String key) {
String code = "";
if (key.contains("@")) {
String[] keys = key.split("@");
key = keys[0];
code = keys[1];
}
return IPanTool.typeMatching(type).parse(key, code);
return IPanTool.typeMatching(type, key, code).parse();
}
}

View File

@@ -5,6 +5,8 @@ import cn.qaiu.lz.web.service.UserService;
import cn.qaiu.vx.core.annotaions.Service;
import io.vertx.core.Future;
import java.util.concurrent.TimeUnit;
/**
* lz-web
* <br>Create date 2021/8/27 14:09
@@ -17,6 +19,11 @@ public class UserServiceImpl implements UserService {
@Override
public Future<String> login(SysUser user) {
try {
TimeUnit.SECONDS.sleep(6);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return Future.succeededFuture("111");
}
}

View File

@@ -19,19 +19,21 @@ custom:
# 异步服务线程数
asyncServiceInstances: 4
# server路由(controller层)所在包路径
routerLocations: cn.qaiu.lz.web.http
baseLocations: cn.qaiu.lz
# 路由处理默认超时时间(毫秒)
routeTimeOut: 15000
# 拦截器包路径
interceptorClassPath: cn.qaiu.lz.common.interceptorImpl.DefaultInterceptor
# server层包路径
handlerLocations: cn.qaiu.lz.web.service
# 匹配规则
# 拦截器匹配规则
ignoresReg:
- .*/login$
- .*/test.*$
# 实体类包路径匹配正则
# 参数注入的实体类包路径匹配正则 (防止同名类引发歧义)
entityPackagesReg:
- ^cn\.qaiu\.lz\.web\.model\..*
# 数据源配置
dataSource:
provider_class: io.vertx.ext.jdbc.spi.impl.HikariCPDataSourceProvider

View File

@@ -1,7 +1,6 @@
# 要激活的配置: dev--连接本地数据库; prod连接线上数据库
active: dev
# 框架版本号 和主版本号
version_vertx: 4.4.1
# 版本号
version_app: 0.1.6
# 公司名称 -> LOGO版权文字
copyright: QAIU

View File

@@ -46,15 +46,14 @@ Content-Disposition: form-data; name="email"
--WebAppBoundary
Content-Disposition: form-data; name="joinProToken"
--WebAppBoundary--
###
https://cowtransfer.com/core/api/transfer/share/download?transferGuid=eb9df924-7b29-496b-8147-96762fc81d28&title=spring-play
###
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch web-service/src/main/resources/http-tools/test.http' --prune-empty --tag-name-filter cat -- --all
git push origin master --force
rmdir .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now
https://cowtransfer.com/core/api/transfer/share/download?transferGuid=
###
https://cowtransfer.com/core/api/transfer/share/download?transferGuid=eb9df924-7b29-496b-8147-96762fc81d28

View File

@@ -24,4 +24,13 @@ https://developer.lanzoug.com/file/?VDJbZVxtADFSWwY+U2YHa1FuU2tTYgBnBnUGZFNmWylS
###
https://developer.lanzoug.com/file/?VTNVa1tqAjMFDAM7BDEAbAE+U2tfbgZhBnVbOQUwVCYEb1IoAToCNwQhVnRXLlcyVWAEdl9uVzkEbFYxVm5VeVVlVSxbNwJ4BWADeAQyAGgBNVN4X3oGbQZxW3sFP1Q8BGhSYAEDAj8ENlY9VzJXZ1U3BDFfMldlBDFWaVY9VXJVM1VxWzsCZwVlA2QEYAAwAWtTYF8wBiIGcVstBWRUZwQ0UjcBbwJ5BGJWNVcsV2RVOgQuX2NXZgQ2VjJWMlVhVWdVNlswAm8FagMxBGAANgE6UzdfYwZgBjFbbAU6VGwEZVIyAWQCZQRkVjZXMFdmVTcENV8uVy8EalYgVixVIVUmVWdbdAI/BTcDaARhADEBblNvXzQGPQY5W3sFLVQ8BGlSYAE6AmsEY1Y2VztXY1U/BDFfM1dnBDRWZFYkVXpVc1VkW2oCIQVuA2QEZgA5AW5TZl8wBjYGMFtkBWFUcwRxUnUBKwJrBGNWNlc7V2NVPwQxXzJXZQQzVmdWLFUhVTxVcls7AmcFYgNnBH4AMwFoU2RfLgY1BjVbawV3VGIEPA==
### 20230819新规则
POST /ajaxm.php
# var wsk_sign = 'c20230818';
# var aihidcms = 'J5Nh';
# var iucjdsd = '';
# var ws_sign = 'c20230818';
# var sasign = 'AGZQbgk4UGEDCgo1ATEGOlY_aBTlSNVRiV2gEMlA1WmkBJ1R3AWFUMVY2VDsDZQE0Vj4CMgNsADdXZw_c_c';
# var ajaxdata = '?ctdf';
data : { 'action':'downprocess','signs':ajaxdata,'sign':sasign,'websign':iucjdsd,'websignkey':aihidcms,'ves':1 }

View File

@@ -10,25 +10,44 @@ content-type: application/json
{"pwd_id":"33197dd53ace4","passcode":"","share_for_transfer":true}
### UCpan 第二步 获取fid,share_fid_token GET传参pwd_id,passcode,stoken
https://pc-api.uc.cn/1/clouddrive/transfer_share/detail?pwd_id=33197dd53ace4&passcode=&stoken=W5b1n2jeFld5RmIusaVOr3vA0vVSCWYQ7Mz8bT2coZM%3D
https://pc-api.uc.cn/1/clouddrive/transfer_share/detail?pwd_id=33197dd53ace4&passcode=&stoken=4lXGIeQ6rdqjuOPW1MHJpqrQR3RWGFKSAAjpTibsR%2B8%3D
content-type: application/json
### UCpan 第二步获取下载链接 POST json传入fids(fid),pwd_id,stoken,fids_token(share_fid_token)
POST https://pc-api.uc.cn/1/clouddrive/file/download?entry=ft&fr=pc&pr=UCBrowser
content-type: application/json
#Cookie: __pus=7576a6d3a511ad7b4c5649a1d89c29ffAAQ06zBxHWghrwEbKRdqBrhXssuYiMIwLLVzi1f2K6qnSL95A79GIxXDEPlYS3NaPjDWOcWVuvbQ3HqTfvqRKr29
{
"fids": [
"54c3cd90ed3e45119bb96ed99a562d40"
],
"pwd_id": "33197dd53ace4",
"stoken": "W5b1n2jeFld5RmIusaVOr3vA0vVSCWYQ7Mz8bT2coZM=",
"stoken": "7P02U9tWJEkkMgbXaIJxAQyBiqcfPdkbDZ6XoiYsBiA=",
"fids_token": [
"4cb5eabb0ce5a26d12ae5ab8acf68aec"
"e8a52adcda41d9e218e732b5de549d2a"
]
}
###
# @no-redirect
https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/646b0de6e9f13000c9b14ba182b805312795a82a/646b0de6717e1bfa5bb44dd2a456f103c5177850?Expires=1690188688&OSSAccessKeyId=LTAIyYfxTqY7YZsg&Signature=gB3rN%2FxPal3ZpReRkB1M4cnvGF4%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B%20filename%3DC%23%20Shell%20%28C%23%20Offline%20Compiler%29_2.5.16.apks&callback-var=eyJ4OmF1IjoiLSIsIng6c3AiOiIxOTkiLCJ4OnRva2VuIjoiMi0wNDBjYjFjMDNjNzU1YWY1NDc0NjkxNjNmOTYzYWY2NC0yLTctNjE0NDAtZGFjYjM2NjViYmFhNGY1ZTlkMzc4MDBlYzY0MDMxNjAtYTU2MGJiMmU1MzhlNzY0OTFkMDY1MjA2OGRiNmEzMzEiLCJ4OnR0bCI6IjEwODAwIn0%3D&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImNsaWVudF90b2tlblwiOiR7cXVlcnlTdHJpbmcuY2xpZW50X3Rva2VufX0ifQ%3D%3D&ud=4-0-5-0-6-N-3-ft-0-2&__pus=7576a6d3a511ad7b4c5649a1d89c29ffAAQ06zBxHWghrwEbKRdqBrhXssuYiMIwLLVzi1f2K6qnSL95A79GIxXDEPlYS3NaPjDWOcWVuvbQ3HqTfvqRKr29
https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/646b0de6e9f13000c9b14ba182b805312795a82a/646b0de6717e1bfa5bb44dd2a456f103c5177850?Expires=1691488145&OSSAccessKeyId=LTAIyYfxTqY7YZsg&Signature=MvUiIWszmMncqDrsLV%2BlL1HpuYw%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B%20filename%3DC%23%20Shell%20%28C%23%20Offline%20Compiler%29_2.5.16.apks&callback-var=eyJ4OmF1IjoiLSIsIng6c3AiOiIxOTkiLCJ4OnRva2VuIjoiMi1iYzBhNTgxNTUwOGE0NmQwYmE4YzUxYjAyZGEwNjA5Yi01LTctNjE0NDAtZGFjYjM2NjViYmFhNGY1ZTlkMzc4MDBlYzY0MDMxNjAtNGZhNTliY2RkNzhlYTE0MDg0Mjc5OGVlNDMxZWFlMDciLCJ4OnR0bCI6IjEwODAwIn0%3D&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImNsaWVudF90b2tlblwiOiR7cXVlcnlTdHJpbmcuY2xpZW50X3Rva2VufX0ifQ%3D%3D&ud=4-N-5-0-6-N-3-ft-0-2
#Cookie: __pus=7576a6d3a511ad7b4c5649a1d89c29ffAAQ06zBxHWghrwEbKRdqBrhXssuYiMIwLLVzi1f2K6qnSL95A79GIxXDEPlYS3NaPjDWOcWVuvbQ3HqTfvqRKr29
###
https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/646b0de6e9f13000c9b14ba182b805312795a82a/646b0de6717e1bfa5bb44dd2a456f103c5177850?Expires=1691488387&OSSAccessKeyId=LTAIyYfxTqY7YZsg&Signature=WIy4UGCwd9eNdUnSexRVFUCFZcM%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B%20filename%3DC%23%20Shell%20%28C%23%20Offline%20Compiler%29_2.5.16.apks&callback-var=eyJ4OmF1IjoiLSIsIng6c3AiOiIxOTkiLCJ4OnRva2VuIjoiMi0wNDBjYjFjMDNjNzU1YWY1NDc0NjkxNjNmOTYzYWY2NC0yLTctNjE0NDAtZGFjYjM2NjViYmFhNGY1ZTlkMzc4MDBlYzY0MDMxNjAtYTU2MGJiMmU1MzhlNzY0OTFkMDY1MjA2OGRiNmEzMzEiLCJ4OnR0bCI6IjEwODAwIn0%3D&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImNsaWVudF90b2tlblwiOiR7cXVlcnlTdHJpbmcuY2xpZW50X3Rva2VufX0ifQ%3D%3D&ud=4-0-5-0-6-N-3-ft-0-2
###
#@no-cookie-jar
https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/646b0de6e9f13000c9b14ba182b805312795a82a/646b0de6717e1bfa5bb44dd2a456f103c5177850?Expires=1691488539&OSSAccessKeyId=LTAIyYfxTqY7YZsg&Signature=rhD0OQTq2CuMUvp0ZphStKiyyw8%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B%20filename%3DC%23%20Shell%20%28C%23%20Offline%20Compiler%29_2.5.16.apks&callback-var=eyJ4OmF1IjoiLSIsIng6c3AiOiIxOTkiLCJ4OnRva2VuIjoiMi02YTU3OGNkNjYyMTQzZWI4ODFjZTE0ZGYyNjk5OTQ4OS01LTctNjE0NDAtZGFjYjM2NjViYmFhNGY1ZTlkMzc4MDBlYzY0MDMxNjAtYzlhYWI1YjA5ZDNhYTA5MWU4NTJjNTJlNGRjYWJkZDYiLCJ4OnR0bCI6IjEwODAwIn0%3D&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImNsaWVudF90b2tlblwiOiR7cXVlcnlTdHJpbmcuY2xpZW50X3Rva2VufX0ifQ%3D%3D&ud=4-N-5-0-6-N-3-ft-0-2
Cookie: __pugs=efc5f3f9c041af5dc62eea4481901cbbAAT912628i+uT/WMwOFWBjJ1TjbKGC1j6cyGHSLVzwuPQP74d+rZXO4xJgdG93MC5DUDdgRJcg5y93waA/KPWDSeDY8LPgjB2Ha2tQ3sQ/MXMoRUi/LRdY3psAyC3YOlUDeFwLtkLAXABRgJhKTw6W0v
###
#@no-cookie-jar
https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/646b0de6e9f13000c9b14ba182b805312795a82a/646b0de6717e1bfa5bb44dd2a456f103c5177850?Expires=1691489999&OSSAccessKeyId=LTAIyYfxTqY7YZsg&Signature=NbQLAEUCkvJxmSsRoIynZ%2BuPMvY%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B%20filename%3DC%23%20Shell%20%28C%23%20Offline%20Compiler%29_2.5.16.apks&callback-var=eyJ4OmF1IjoiLSIsIng6c3AiOiIxOTkiLCJ4OnRva2VuIjoiMi0wNDBjYjFjMDNjNzU1YWY1NDc0NjkxNjNmOTYzYWY2NC0yLTctNjE0NDAtZGFjYjM2NjViYmFhNGY1ZTlkMzc4MDBlYzY0MDMxNjAtYTU2MGJiMmU1MzhlNzY0OTFkMDY1MjA2OGRiNmEzMzEiLCJ4OnR0bCI6IjEwODAwIn0%3D&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImNsaWVudF90b2tlblwiOiR7cXVlcnlTdHJpbmcuY2xpZW50X3Rva2VufX0ifQ%3D%3D&ud=4-0-5-0-6-N-3-ft-0-2
Cookie: __puus=dc48cb12577eb3df6fe84fdea250ad6fAAOF0LBv/M4HTtkYfuUNdcVLXHZl1x2mw8NQSdxo5abymS+irugphlPNv5kwQZkDI+pXaeOD22v/whNQT5AwUULF0q1nSNXmHqxr20AJjXlEhvbIZNgUfwmw8aOCyarrLi7o7w6w0Rod4DLCSeYGwlTF3P9jMcqCM+WqWHnxKY6i8gaXZkHLObatSHkwivB7Xpc=
Referer: https://fast.uc.cn/

View File

@@ -28,6 +28,10 @@ GET http://127.0.0.1:6400/cow/e4f41b51b5da4f
# @no-redirect
GET http://127.0.0.1:6400/parser?url=https://cowtransfer.com/s/9a644fe3e3a748
### 奶牛
# @no-redirect
GET http://127.0.0.1:6400/parser?url=https://goldrepo.cowtransfer.com/s/026a638795634b
### 移动云空间 https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=81027a5c99af5b11ca004966c945cce6W9Bf2&isShare=1
# @no-redirect
GET http://127.0.0.1:6400/parser?url=https://www.ecpan.cn/web//yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=81027a5c99af5b11ca004966c945cce6W9Bf2&isShare=1
@@ -65,10 +69,10 @@ GET http://127.0.0.1:6400/fj/tIfhRqH
### 360亿方云
# @no-redirect
GET http://127.0.0.1:6400/parser?url=https://v2.fangcloud.com/share/2f238f7714cf61cdc631d23d18
GET http://127.0.0.1:6400/parser?url=https://v2.fangcloud.com/sharing/fb54bdf03c66c04334fe3687a3
### 360亿方云
GET http://127.0.0.1:6400/json/fc/30646fefc8bf936a4766ab8a5e
GET http://127.0.0.1:6400/json/fc/fb54bdf03c66c04334fe3687a3
### 360亿方云
# @no-redirect
@@ -94,6 +98,6 @@ GET http://127.0.0.1:6400/ye/iaKtVv-qOECd
GET http://127.0.0.1:6400/parser?url=https://www.123pan.com/s/iaKtVv-6OECd.html&pwd=DcGe
###
POST http://127.0.0.1:6400/login1
POST http://127.0.0.1:6400/login

View File

@@ -0,0 +1,46 @@
/**
* 蓝奏云解析器js签名获取工具
*/
var signObj;
var $, jQuery;
$ = jQuery = function () {
return new jQuery.fn.init();
}
jQuery.fn = jQuery.prototype = {
init: function () {
return {
focus: function (a) {
},
keyup: function(a) {
},
ajax: function (obj) {
signObj = obj
}
}
},
}
jQuery.fn.init.prototype = jQuery.fn;
// 伪装jquery.ajax函数获取关键数据
$.ajax = function (obj) {
signObj = obj
}
var document = {
getElementById: function (v) {
return {
value: 'v'
}
},
}

View File

@@ -1,4 +1,5 @@
/*
https://statics.123pan.com/share-static/dist/umi.fb72555e.js
eaefamemdead
eaefameidldy
_0x4f141a(1690439821|5790548|/b/api/share/download/info|web|3|1946841013) = 秘钥
@@ -38,18 +39,7 @@ function _0x1b5d95(_0x278d1a) {
function _0x4f141a(_0x4075b1) {
for (var _0x4eddcb = arguments['length'] > 0x1 && void 0x0 !== arguments[0x1] ? arguments[0x1] : 0xa,
_0x4ee01e = function(_0x3bb99e) {
var _0x3bb99e = _0x3bb99e['replace'](/\\r\\n/g, '\x5cn');
for (var _0x585459 = '', _0x15c988 = 0x0; _0x15c988 < _0x3bb99e['length']; _0x15c988++) {
var _0x36bb3e = _0x3bb99e['charCodeAt'](_0x15c988);
_0x36bb3e < 0x80 ? _0x585459 += String['fromCharCode'](_0x36bb3e) : _0x36bb3e > 0x7f && _0x36bb3e < 0x800 ? (_0x585459 += String['fromCharCode'](_0x36bb3e >> 0x6 | 0xc0),
_0x585459 += String['fromCharCode'](0x3f & _0x36bb3e | 0x80)) : (_0x585459 += String['fromCharCode'](_0x36bb3e >> 0xc | 0xe0),
_0x585459 += String['fromCharCode'](_0x36bb3e >> 0x6 & 0x3f | 0x80),
_0x585459 += String['fromCharCode'](0x3f & _0x36bb3e | 0x80));
}
return _0x585459;
}, _0x2fc680 = function() {
_0x2fc680 = function() {
for (var _0x515c63, _0x361314 = [], _0x4cbdba = 0x0; _0x4cbdba < 0x100; _0x4cbdba++) {
_0x515c63 = _0x4cbdba;
for (var _0x460960 = 0x0; _0x460960 < 0x8; _0x460960++)
@@ -59,7 +49,7 @@ function _0x4f141a(_0x4075b1) {
return _0x361314;
},
_0x4aed86 = _0x2fc680(),
_0x5880f0 = _0x4ee01e(_0x4075b1),
_0x5880f0 = _0x4075b1,
_0x492393 = -0x1, _0x25d82c = 0x0;
_0x25d82c < _0x5880f0['length'];
_0x25d82c++)

View File

@@ -0,0 +1,30 @@
package cn.qaiu.vx.core.util;
import cn.qaiu.lz.common.util.SnowflakeIdWorker;
import org.junit.Test;
public class SnowflakeIdWorkerTest {
@Test
public void idWorker() {
final SnowflakeIdWorker idWorker = SnowflakeIdWorker.idWorker();
for (int i = 0; i < 100; i++) {
long id = idWorker.nextId();
System.out.println(Long.toBinaryString(id));
System.out.println(id);
System.out.println("------------");
}
}
@Test
public void idWorkerCluster() {
final SnowflakeIdWorker snowflakeIdWorkerCluster = SnowflakeIdWorker.idWorkerCluster(0, 1);
for (int i = 0; i < 100; i++) {
long id = snowflakeIdWorkerCluster.nextId();
System.out.println(Long.toBinaryString(id));
System.out.println(id);
System.out.println("------------\n");
}
}
}

View File

@@ -65,8 +65,8 @@ public class TestAESUtil {
@Test
public void testKeyAuth(){
System.out.println(AESUtils.getAuthKey("/b/api/share/download/info"));
System.out.println(AESUtils.getAuthKey("/b/api/share/download/info"));
System.out.println(AESUtils.getAuthKey("/a/api/share/download/info"));
System.out.println(AESUtils.getAuthKey("/a/api/share/download/info"));
System.out.println(AESUtils.getAuthKey("/b/api/share/get"));
}