From 5052fea9efbdb128d853903b6b4a08c76832d7e6 Mon Sep 17 00:00:00 2001 From: QAIU <736226400@qq.com> Date: Thu, 6 Feb 2025 16:52:06 +0800 Subject: [PATCH] =?UTF-8?q?MySQL=E6=94=AF=E6=8C=81,=20=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core-database/pom.xml | 6 + .../main/java/cn/qaiu/db/ddl/Constraint.java | 2 +- .../java/cn/qaiu/db/ddl/CreateDatabase.java | 67 ++++++++++ .../java/cn/qaiu/db/pool/JDBCPoolInit.java | 27 +++- .../main/java/cn/qaiu/db/pool/JDBCType.java | 47 ++++++- .../main/java/cn/qaiu/db/pool/JDBCUtil.java | 18 --- note.txt | 10 +- .../main/java/cn/qaiu/parser/impl/UcTool.java | 122 ++++++++++++++++++ .../cn/qaiu/lz/common/cache/CacheManager.java | 87 ++++++++++--- .../qaiu/lz/web/model/ApiStatisticsInfo.java | 4 +- .../cn/qaiu/lz/web/model/CacheLinkInfo.java | 2 +- .../lz/web/service/impl/DbServiceImpl.java | 12 +- web-service/src/main/resources/app-dev.yml | 15 +-- .../src/main/resources/http-tools/pan-uc.http | 108 ++++++++++++++++ 14 files changed, 465 insertions(+), 62 deletions(-) create mode 100644 core-database/src/main/java/cn/qaiu/db/ddl/CreateDatabase.java delete mode 100644 core-database/src/main/java/cn/qaiu/db/pool/JDBCUtil.java create mode 100644 parser/src/main/java/cn/qaiu/parser/impl/UcTool.java diff --git a/core-database/pom.xml b/core-database/pom.xml index 9c15186..507a6a3 100644 --- a/core-database/pom.xml +++ b/core-database/pom.xml @@ -59,6 +59,12 @@ vertx-jdbc-client ${vertx.version} + + com.mysql + mysql-connector-j + 9.2.0 + + diff --git a/core-database/src/main/java/cn/qaiu/db/ddl/Constraint.java b/core-database/src/main/java/cn/qaiu/db/ddl/Constraint.java index 3b234bf..cfcad14 100644 --- a/core-database/src/main/java/cn/qaiu/db/ddl/Constraint.java +++ b/core-database/src/main/java/cn/qaiu/db/ddl/Constraint.java @@ -32,7 +32,7 @@ public @interface Constraint { */ String defaultValue() default ""; /** - * 默认值是否是函数 + * 默认值是否是函数 like value=NOW() * @return false 不是函数 */ boolean defaultValueIsFunction() default false; diff --git a/core-database/src/main/java/cn/qaiu/db/ddl/CreateDatabase.java b/core-database/src/main/java/cn/qaiu/db/ddl/CreateDatabase.java new file mode 100644 index 0000000..6749c15 --- /dev/null +++ b/core-database/src/main/java/cn/qaiu/db/ddl/CreateDatabase.java @@ -0,0 +1,67 @@ +package cn.qaiu.db.ddl; + +import cn.qaiu.db.pool.JDBCPoolInit; +import io.vertx.core.json.JsonObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CreateDatabase { + + private static final Logger LOGGER = LoggerFactory.getLogger(JDBCPoolInit.class); + + /** + * 解析数据库URL,获取数据库名 + * @param url 数据库URL + * @return 数据库名 + */ + public static String getDatabaseName(String url) { + // 正则表达式匹配数据库名 + String regex = "jdbc:mysql://[^/]+/(\\w+)(\\?.*)?"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(url); + + if (matcher.find()) { + return matcher.group(1); + } else { + throw new IllegalArgumentException("Invalid database URL: " + url); + } + } + + /** + * 使用JDBC原生方法创建数据库 + * @param url 数据库连接URL + * @param user 数据库用户名 + * @param password 数据库密码 + */ + public static void createDatabase(String url, String user, String password) { + String dbName = getDatabaseName(url); + LOGGER.info(">>>>>>>>>>> 创建数据库:'{}' <<<<<<<<<<<< ", dbName); + + // 去掉数据库名,构建不带数据库名的URL + String baseUrl = url.substring(0, url.lastIndexOf("/") + 1) + "?characterEncoding=UTF-8&useUnicode=true"; + + try (Connection conn = DriverManager.getConnection(baseUrl, user, password); + Statement stmt = conn.createStatement()) { + // 创建数据库 + stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS " + dbName + " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); + LOGGER.info(">>>>>>>>>>> 数据库'{}'创建成功 <<<<<<<<<<<<", dbName); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public static void createDatabase(JsonObject dbConfig) { + createDatabase( + dbConfig.getString("jdbcUrl"), + dbConfig.getString("username"), + dbConfig.getString("password") + ); + } +} diff --git a/core-database/src/main/java/cn/qaiu/db/pool/JDBCPoolInit.java b/core-database/src/main/java/cn/qaiu/db/pool/JDBCPoolInit.java index 2fdbcb9..602eee3 100644 --- a/core-database/src/main/java/cn/qaiu/db/pool/JDBCPoolInit.java +++ b/core-database/src/main/java/cn/qaiu/db/pool/JDBCPoolInit.java @@ -1,13 +1,18 @@ package cn.qaiu.db.pool; import cn.qaiu.db.ddl.CreateTable; +import cn.qaiu.db.ddl.CreateDatabase; import cn.qaiu.vx.core.util.VertxHolder; import io.vertx.core.Vertx; import io.vertx.core.json.JsonObject; import io.vertx.jdbcclient.JDBCPool; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * 初始化JDBC *
Create date 2021/8/10 12:04 @@ -17,18 +22,32 @@ import org.slf4j.LoggerFactory; public class JDBCPoolInit { private static final Logger LOGGER = LoggerFactory.getLogger(JDBCPoolInit.class); + + private static final String providerClass = io.vertx.ext.jdbc.spi.impl.HikariCPDataSourceProvider.class.getName(); + private JDBCPool pool = null; JsonObject dbConfig; Vertx vertx = VertxHolder.getVertxInstance(); String url; + private final JDBCType type; private static JDBCPoolInit instance; + public JDBCType getType() { + return type; + } + public JDBCPoolInit(Builder builder) { this.dbConfig = builder.dbConfig; this.url = builder.url; - this.type = builder.type; + this.type = JDBCType.getJDBCTypeByURL(builder.url); + if (StringUtils.isBlank(builder.dbConfig.getString("provider_class"))) { + builder.dbConfig.put("provider_class", providerClass); + } + if (StringUtils.isBlank(builder.dbConfig.getString("driverClassName"))) { + builder.dbConfig.put("driverClassName", this.type.getDriverClassName()); + } } public static Builder builder() { @@ -42,12 +61,10 @@ public class JDBCPoolInit { public static class Builder { private JsonObject dbConfig; private String url; - private JDBCType type; public Builder config(JsonObject dbConfig) { this.dbConfig = dbConfig; this.url = dbConfig.getString("jdbcUrl"); - this.type = JDBCUtil.getJDBCType(dbConfig.getString("driverClassName")); return this; } @@ -59,7 +76,6 @@ public class JDBCPoolInit { } } - /** * init h2db
* 这个方法只允许调用一次 @@ -72,6 +88,9 @@ public class JDBCPoolInit { // 初始化数据库连接 // 初始化连接池 + if (type == JDBCType.MySQL) { + CreateDatabase.createDatabase(dbConfig); + } pool = JDBCPool.pool(vertx, dbConfig); CreateTable.createTable(pool, type); LOGGER.info("数据库连接初始化: URL=" + url); diff --git a/core-database/src/main/java/cn/qaiu/db/pool/JDBCType.java b/core-database/src/main/java/cn/qaiu/db/pool/JDBCType.java index 7cccb3e..5430b9b 100644 --- a/core-database/src/main/java/cn/qaiu/db/pool/JDBCType.java +++ b/core-database/src/main/java/cn/qaiu/db/pool/JDBCType.java @@ -1,9 +1,52 @@ package cn.qaiu.db.pool; +import org.apache.commons.lang3.StringUtils; + /** * @author QAIU - * @date 2023/10/10 14:06 + * @since 2023/10/10 14:06 */ public enum JDBCType { - MySQL, H2DB + // 添加驱动类型字段 + MySQL("com.mysql.cj.jdbc.Driver", "jdbc:mysql:"), + H2DB("org.h2.Driver", "jdbc:h2:"); + + private final String driverClassName; // 驱动类名 + private final String urlPrefix; // JDBC URL 前缀 + + // 构造函数 + JDBCType(String driverClassName, String urlPrefix) { + this.driverClassName = driverClassName; + this.urlPrefix = urlPrefix; + } + + // 获取驱动类名 + public String getDriverClassName() { + return driverClassName; + } + + // 获取 JDBC URL 前缀 + public String getUrlPrefix() { + return urlPrefix; + } + + // 根据驱动类名获取 JDBC 类型 + public static JDBCType getJDBCType(String driverClassName) { + for (JDBCType jdbcType : values()) { + if (jdbcType.getDriverClassName().equalsIgnoreCase(driverClassName)) { + return jdbcType; + } + } + throw new RuntimeException("不支持的SQL驱动类型: " + driverClassName); + } + + // 根据 JDBC URL 获取 JDBC 类型 + public static JDBCType getJDBCTypeByURL(String jdbcURL) { + for (JDBCType jdbcType : values()) { + if (StringUtils.startsWithIgnoreCase(jdbcURL, jdbcType.getUrlPrefix())) { + return jdbcType; + } + } + throw new RuntimeException("不支持的SQL驱动类型: " + jdbcURL); + } } diff --git a/core-database/src/main/java/cn/qaiu/db/pool/JDBCUtil.java b/core-database/src/main/java/cn/qaiu/db/pool/JDBCUtil.java deleted file mode 100644 index 8f25366..0000000 --- a/core-database/src/main/java/cn/qaiu/db/pool/JDBCUtil.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.qaiu.db.pool; - -/** - * @author QAIU - * @date 2023/10/10 14:05 - */ -public class JDBCUtil { - public static JDBCType getJDBCType(String deviceName) { - switch (deviceName) { - case "com.mysql.cj.jdbc.Driver": - case "com.mysql.jdbc.Driver": - return JDBCType.MySQL; - case "org.h2.Driver": - return JDBCType.H2DB; - } - throw new RuntimeException("不支持的SQL驱动类型: " + deviceName); - } -} diff --git a/note.txt b/note.txt index d4cc93b..38691b7 100644 --- a/note.txt +++ b/note.txt @@ -60,7 +60,15 @@ jwt鉴权用户 文件信息: 文件/文件夹, 文件数量, 文件大小, 文件类型; 链接信息: 解析次数, 缓存次数等) 微服务设计: - +TODO + +后台管理: + 菜单: + 网盘管理: token配置, 启用/禁用 + 短链管理: 短链列表, 新增, 删除 + 解析统计: 下载次数统计, 下载流量统计, 详细解析列表 + 状态监视: 服务请求并发数; 来源IP列表: 拉黑, 限制次数; Nginx + 系统配置: 管理员账户, 系统参数: 域名配置, 预览URL, diff --git a/parser/src/main/java/cn/qaiu/parser/impl/UcTool.java b/parser/src/main/java/cn/qaiu/parser/impl/UcTool.java new file mode 100644 index 0000000..7e2527b --- /dev/null +++ b/parser/src/main/java/cn/qaiu/parser/impl/UcTool.java @@ -0,0 +1,122 @@ +package cn.qaiu.parser.impl; + +import cn.qaiu.entity.ShareLinkInfo; +import cn.qaiu.parser.PanBase; +import io.vertx.core.Future; +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; +import io.vertx.uritemplate.UriTemplate; + +/** + * UC网盘解析 + */ +public class UcTool extends PanBase { + 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/"; + + private static final String FIRST_REQUEST_URL = API_URL_PREFIX + "share/sharepage/token?entry=ft&fr=pc&pr" + + "=UCBrowser"; + + private static final String SECOND_REQUEST_URL = API_URL_PREFIX + "transfer_share/detail?pwd_id={pwd_id}&passcode" + + "={passcode}&stoken={stoken}"; + + private static final String THIRD_REQUEST_URL = API_URL_PREFIX + "file/download?entry=ft&fr=pc&pr=UCBrowser"; + + public UcTool(ShareLinkInfo shareLinkInfo) { + super(shareLinkInfo); + } + + public Future parse() { + var dataKey = shareLinkInfo.getShareKey(); + var passcode = shareLinkInfo.getSharePassword(); + + var jsonObject = JsonObject.of("share_for_transfer", true); + jsonObject.put("pwd_id", dataKey); + jsonObject.put("passcode", passcode); + // 第一次请求 获取文件信息 + client.postAbs(FIRST_REQUEST_URL).sendJsonObject(jsonObject).onSuccess(res -> { + log.debug("第一阶段 {}", res.body()); + var resJson = res.bodyAsJsonObject(); + if (resJson.getInteger("code") != 0) { + fail(FIRST_REQUEST_URL + " 返回异常: " + resJson); + return; + } + var stoken = resJson.getJsonObject("data").getString("stoken"); + // 第二次请求 + client.getAbs(UriTemplate.of(SECOND_REQUEST_URL)) + .setTemplateParam("pwd_id", dataKey) + .setTemplateParam("passcode", passcode) + .setTemplateParam("stoken", stoken) + .send().onSuccess(res2 -> { + log.debug("第二阶段 {}", res2.body()); + JsonObject resJson2 = res2.bodyAsJsonObject(); + if (resJson2.getInteger("code") != 0) { + fail(FIRST_REQUEST_URL + " 返回异常: " + resJson2); + return; + } + // 文件信息 + var info = resJson2.getJsonObject("data").getJsonArray("list").getJsonObject(0); + // 第二次请求 + var bodyJson = JsonObject.of() + .put("fids", JsonArray.of(info.getString("fid"))) + .put("pwd_id", dataKey) + .put("stoken", stoken) + .put("fids_token", JsonArray.of(info.getString("share_fid_token"))); + client.postAbs(THIRD_REQUEST_URL).sendJsonObject(bodyJson) + .onSuccess(res3 -> { + log.debug("第三阶段 {}", res3.body()); + var resJson3 = res3.bodyAsJsonObject(); + if (resJson3.getInteger("code") != 0) { + fail(FIRST_REQUEST_URL + " 返回异常: " + resJson2); + return; + } + promise.complete(resJson3.getJsonArray("data").getJsonObject(0).getString("download_url")); + }).onFailure(handleFail(THIRD_REQUEST_URL)); + + }).onFailure(handleFail(SECOND_REQUEST_URL)); + } + ).onFailure(handleFail(FIRST_REQUEST_URL)); + return promise.future(); + } + + public static void main(String[] args) { + + // https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/ + // 646b0de6e9f13000c9b14ba182b805312795a82a/ + // 646b0de6717e1bfa5bb44dd2a456f103c5177850? + // Expires=1737784900&OSSAccessKeyId=LTAI5tJJpWQEfrcKHnd1LqsZ& + // Signature=oBVV3anhv3tBKanHUcEIsktkB%2BM%3D&x-oss-traffic-limit=503316480 + // &response-content-disposition=attachment%3B%20filename%3DC%2523%2520Shell%2520%2528C%2523%2520Offline%2520Compiler%2529_2.5.16.apks + // %3Bfilename%2A%3Dutf-8%27%27C%2523%2520Shell%2520%2528C%2523%2520Offline%2520Compiler%2529_2.5.16.apks + + //eyJ4OmF1IjoiLSIsIng6dWQiOiI0LU4tNS0wLTYtTi0zLWZ0LTAtMi1OLU4iLCJ4OnNwIjoiMTAwIiwieDp0b2tlbiI6IjQtZjY0ZmMxMDFjZmQxZGVkNTRkMGM0NmMzYzliMzkyOWYtNS03LTE1MzYxMS1kYWNiMzY2NWJiYWE0ZjVlOWQzNzgwMGVjNjQwMzE2MC0wLTAtMC0wLTQ5YzUzNTE3OGIxOTY0YzhjYzUwYzRlMDk5MTZmYWRhIiwieDp0dGwiOiIxMDgwMCJ9 + //eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ1ZFwiOiR7eDp1ZH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImR0X3NwXCI6JHt4OmR0X3NwfSxcImhzcFwiOiR7eDpoc3B9LFwiY2xpZW50X3Rva2VuXCI6JHtxdWVyeVN0cmluZy5jbGllbnRfdG9rZW59fSJ9 + //callback-var {"x:au":"-","x:ud":"4-N-5-0-6-N-3-ft-0-2-N-N","x:sp":"100","x:token":"4-f64fc101cfd1ded54d0c46c3c9b3929f-5-7-153611-dacb3665bbaa4f5e9d37800ec6403160-0-0-0-0-49c535178b1964c8cc50c4e09916fada","x:ttl":"10800"} + //callback {"callbackBodyType":"application/json","callbackStage":"before-execute","callbackFailureAction":"ignore","callbackUrl":"https://auth-cdn.uc.cn/outer/oss/checkplay","callbackBody":"{\"host\":${httpHeader.host},\"size\":${size},\"range\":${httpHeader.range},\"referer\":${httpHeader.referer},\"cookie\":${httpHeader.cookie},\"method\":${httpHeader.method},\"ip\":${clientIp},\"port\":${clientPort},\"object\":${object},\"sp\":${x:sp},\"ud\":${x:ud},\"token\":${x:token},\"au\":${x:au},\"ttl\":${x:ttl},\"dt_sp\":${x:dt_sp},\"hsp\":${x:hsp},\"client_token\":${queryString.client_token}}"} + + /* + // callback-var +{ + "x:au": "-", + "x:ud": "4-N-5-0-6-N-3-ft-0-2-N-N", + "x:sp": "100", + "x:token": "4-f64fc101cfd1ded54d0c46c3c9b3929f-5-7-153611-dacb3665bbaa4f5e9d37800ec6403160-0-0-0-0-49c535178b1964c8cc50c4e09916fada", + "x:ttl": "10800" +} + +// callback +{ + "callbackBodyType": "application/json", + "callbackStage": "before-execute", + "callbackFailureAction": "ignore", + "callbackUrl": "https://auth-cdn.uc.cn/outer/oss/checkplay", + "callbackBody": "{\"host\":${httpHeader.host},\"size\":${size},\"range\":${httpHeader.range},\"referer\":${httpHeader.referer},\"cookie\":${httpHeader.cookie},\"method\":${httpHeader.method},\"ip\":${clientIp},\"port\":${clientPort},\"object\":${object},\"sp\":${x:sp},\"ud\":${x:ud},\"token\":${x:token},\"au\":${x:au},\"ttl\":${x:ttl},\"dt_sp\":${x:dt_sp},\"hsp\":${x:hsp},\"client_token\":${queryString.client_token}}" +} + */ + + new UcTool(ShareLinkInfo.newBuilder().shareUrl("https://fast.uc.cn/s/33197dd53ace4").shareKey("33197dd53ace4").build()).parse().onSuccess( + System.out::println + ); + } +} diff --git a/web-service/src/main/java/cn/qaiu/lz/common/cache/CacheManager.java b/web-service/src/main/java/cn/qaiu/lz/common/cache/CacheManager.java index cbc4800..8d8564f 100644 --- a/web-service/src/main/java/cn/qaiu/lz/common/cache/CacheManager.java +++ b/web-service/src/main/java/cn/qaiu/lz/common/cache/CacheManager.java @@ -1,6 +1,7 @@ package cn.qaiu.lz.common.cache; import cn.qaiu.db.pool.JDBCPoolInit; +import cn.qaiu.db.pool.JDBCType; import cn.qaiu.lz.web.model.CacheLinkInfo; import io.vertx.core.Future; import io.vertx.core.Promise; @@ -8,13 +9,17 @@ import io.vertx.core.json.JsonObject; import io.vertx.jdbcclient.JDBCPool; import io.vertx.sqlclient.Row; import io.vertx.sqlclient.templates.SqlTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; public class CacheManager { private final JDBCPool jdbcPool = JDBCPoolInit.instance().getPool(); + private final JDBCType jdbcType = JDBCPoolInit.instance().getType(); + private static final Logger LOGGER = LoggerFactory.getLogger(CacheManager.class); public Future get(String cacheKey) { String sql = "SELECT share_key as shareKey, direct_link as directLink, expiration FROM cache_link_info WHERE share_key = #{share_key}"; @@ -33,16 +38,31 @@ public class CacheManager { cacheHit = new CacheLinkInfo(JsonObject.of("cacheHit", false, "shareKey", cacheKey)); } promise.complete(cacheHit); - }).onFailure(Throwable::printStackTrace); + }).onFailure(e->{ + promise.fail(e); + LOGGER.error("cache get:", e); + }); return promise.future(); } // 插入或更新缓存数据 public Future cacheShareLink(CacheLinkInfo cacheLinkInfo) { - String sql = "MERGE INTO cache_link_info (share_key, direct_link, expiration) " + - "KEY (share_key) " + - "VALUES (#{shareKey}, #{directLink}, #{expiration})"; + String sql; + if (jdbcType == JDBCType.MySQL) { + sql = """ + INSERT INTO cache_link_info (share_key, direct_link, expiration) + VALUES (#{shareKey}, #{directLink}, #{expiration}) + ON DUPLICATE KEY UPDATE + direct_link = VALUES(direct_link), + expiration = VALUES(expiration); + """; + } else { // 运行H2 + sql = "MERGE INTO cache_link_info (share_key, direct_link, expiration) " + + "KEY (share_key) " + + "VALUES (#{shareKey}, #{directLink}, #{expiration})"; + } + // 直接传递 CacheLinkInfo 实体类 return SqlTemplate.forUpdate(jdbcPool, sql) @@ -55,11 +75,23 @@ public class CacheManager { public Future updateTotalByField(String shareKey, CacheTotalField field) { Promise promise = Promise.promise(); String fieldLower = field.name().toLowerCase(); - String sql = """ + String sql; + if (jdbcType == JDBCType.MySQL) { // 假设你有一个标识当前数据库类型的布尔变量 + sql = """ + INSERT INTO `api_statistics_info` (`pan_type`, `share_key`, `{field}`, `update_ts`) + VALUES (#{panType}, #{shareKey}, #{total}, #{ts}) + ON DUPLICATE KEY UPDATE + `pan_type` = VALUES(`pan_type`), + `{field}` = VALUES(`{field}`), + `update_ts` = VALUES(`update_ts`); + """.replace("{field}", fieldLower); + } else { // 运行H2 + sql = """ MERGE INTO `api_statistics_info` (`pan_type`, `share_key`, `{field}`, `update_ts`) KEY (`share_key`) VALUES (#{panType}, #{shareKey}, #{total}, #{ts}) """.replace("{field}", fieldLower); + } getShareKeyTotal(shareKey, fieldLower).onSuccess(total -> { Integer newTotal = (total == null ? 0 : total) + 1; @@ -71,7 +103,10 @@ public class CacheManager { put("ts", System.currentTimeMillis()); }}) .onSuccess(res -> promise.complete(res.rowCount())) - .onFailure(Throwable::printStackTrace); + .onFailure(e->{ + promise.fail(e); + LOGGER.error("updateTotalByField: ", e); + }); }); return promise.future(); } @@ -84,10 +119,12 @@ public class CacheManager { public Future getShareKeyTotal(String shareKey, String name) { String sql = """ - select `share_key`, sum({total_name}) sum_num - from `api_statistics_info` - group by `share_key` having `share_key` = #{shareKey}; + SELECT `share_key`, SUM({total_name}) AS sum_num + FROM `api_statistics_info` + WHERE `share_key` = #{shareKey} + GROUP BY `share_key`; """.replace("{total_name}", name); + Promise promise = Promise.promise(); Map paramMap = new HashMap<>(); paramMap.put("shareKey", shareKey); @@ -98,16 +135,21 @@ public class CacheManager { Integer total = res.iterator().hasNext() ? res.iterator().next().getInteger("sum_num") : null; promise.complete(total); + }).onFailure(e->{ + promise.fail(e); + LOGGER.error("getShareKeyTotal: ", e); }); return promise.future(); } public Future> getShareKeyTotal(String shareKey) { String sql = """ - select `share_key`, sum(cache_hit_total) hit_total, sum(api_parser_total) parser_total, - from `api_statistics_info` - group by `share_key` having `share_key` = #{shareKey} + SELECT `share_key`, SUM(cache_hit_total) AS hit_total, SUM(api_parser_total) AS parser_total + FROM `api_statistics_info` + WHERE `share_key` = #{shareKey} + GROUP BY `share_key`; """; + Promise> promise = Promise.promise(); Map paramMap = new HashMap<>(); paramMap.put("shareKey", shareKey); @@ -115,16 +157,19 @@ public class CacheManager { .mapTo(Row::toJson) .execute(paramMap) .onSuccess(res -> { - if(res.iterator().hasNext()) { - JsonObject next = res.iterator().next(); - Map resp = new HashMap<>(){{ - put("hit_total" ,next.getInteger("hit_total")); - put("parser_total" ,next.getInteger("parser_total")); - }}; - promise.complete(resp); + if(res.iterator().hasNext()) { + JsonObject next = res.iterator().next(); + Map resp = new HashMap<>(){{ + put("hit_total" ,next.getInteger("hit_total")); + put("parser_total" ,next.getInteger("parser_total")); + }}; + promise.complete(resp); } else { - promise.complete(); - } + promise.complete(); + } + }).onFailure(e->{ + promise.fail(e); + LOGGER.error("getShareKeyTotal0: ", e); }); return promise.future(); } diff --git a/web-service/src/main/java/cn/qaiu/lz/web/model/ApiStatisticsInfo.java b/web-service/src/main/java/cn/qaiu/lz/web/model/ApiStatisticsInfo.java index 7c62fb4..c543911 100644 --- a/web-service/src/main/java/cn/qaiu/lz/web/model/ApiStatisticsInfo.java +++ b/web-service/src/main/java/cn/qaiu/lz/web/model/ApiStatisticsInfo.java @@ -21,13 +21,13 @@ public class ApiStatisticsInfo implements ToJson { /** * pan type 单独拿出来便于统计. */ - @Length(varcharSize = 4) + @Length(varcharSize = 16) private String panType; /** * 分享key type:key */ - @Length(varcharSize = 4096) + @Length(varcharSize = 1024) private String shareKey; /** diff --git a/web-service/src/main/java/cn/qaiu/lz/web/model/CacheLinkInfo.java b/web-service/src/main/java/cn/qaiu/lz/web/model/CacheLinkInfo.java index 8e386f0..06dc427 100644 --- a/web-service/src/main/java/cn/qaiu/lz/web/model/CacheLinkInfo.java +++ b/web-service/src/main/java/cn/qaiu/lz/web/model/CacheLinkInfo.java @@ -23,7 +23,7 @@ public class CacheLinkInfo implements ToJson { /** * 缓存key: type:ShareKey; e.g. lz:xxxx */ - @Length(varcharSize = 4096) + @Length(varcharSize = 1024) private String shareKey; /** diff --git a/web-service/src/main/java/cn/qaiu/lz/web/service/impl/DbServiceImpl.java b/web-service/src/main/java/cn/qaiu/lz/web/service/impl/DbServiceImpl.java index 6b37206..9cbb6f8 100644 --- a/web-service/src/main/java/cn/qaiu/lz/web/service/impl/DbServiceImpl.java +++ b/web-service/src/main/java/cn/qaiu/lz/web/service/impl/DbServiceImpl.java @@ -48,10 +48,11 @@ public class DbServiceImpl implements DbService { JDBCPool client = JDBCPoolInit.instance().getPool(); Promise promise = Promise.promise(); String sql = """ - select sum(api_parser_total) parserTotal,sum("cache_hit_total") cacheTotal, - sum(api_parser_total) + sum("cache_hit_total") total - from "api_statistics_info"; + select sum(api_parser_total) as parserTotal, sum(cache_hit_total) as cacheTotal, + sum(api_parser_total) + sum(cache_hit_total) as total + from api_statistics_info; """; + SqlTemplate.forQuery(client, sql).mapTo(StatisticsInfo.class).execute(new HashMap<>()).onSuccess(row -> { StatisticsInfo info; if ((info = row.iterator().next()) != null) { @@ -59,7 +60,10 @@ public class DbServiceImpl implements DbService { } else { promise.fail("t_parser_log_info查询为空"); } - }).onFailure(promise::fail); + }).onFailure(e->{ + log.error("getStatisticsInfo: ", e); + promise.fail(e); + }); return promise.future(); } } diff --git a/web-service/src/main/resources/app-dev.yml b/web-service/src/main/resources/app-dev.yml index 0eff11e..93a255a 100644 --- a/web-service/src/main/resources/app-dev.yml +++ b/web-service/src/main/resources/app-dev.yml @@ -35,9 +35,8 @@ custom: # 数据源配置 dataSource: - provider_class: io.vertx.ext.jdbc.spi.impl.HikariCPDataSourceProvider - jdbcUrl: jdbc:h2:file:./db/nfdData;MODE=MySQL;DATABASE_TO_UPPER=FALSE - driverClassName: org.h2.Driver + #jdbcUrl: jdbc:mysql://127.0.0.1:3306/nfddata?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false + jdbcUrl: jdbc:h2:file:./db/nfdData111;MODE=MySQL;DATABASE_TO_UPPER=FALSE username: root password: '123456' @@ -49,17 +48,17 @@ cache: defaultDuration: 59 # 具体网盘的缓存配置,如果不加配置则不缓存,每次请求都会请求网盘API,格式:网盘标识: 时长 duration: - ce: + ce: 5 cow: - ec: + ec: 5 fc: - fj: + fj: 20 iz: 20 le: 2879 lz: 20 qq: 9999999 - ws: - ye: + ws: 10 + ye: -1 mne: 30 mqq: 30 mkg: 30 diff --git a/web-service/src/main/resources/http-tools/pan-uc.http b/web-service/src/main/resources/http-tools/pan-uc.http index 0dd2296..e191f85 100644 --- a/web-service/src/main/resources/http-tools/pan-uc.http +++ b/web-service/src/main/resources/http-tools/pan-uc.http @@ -51,3 +51,111 @@ Cookie: __pugs=efc5f3f9c041af5dc62eea4481901cbbAAT912628i+uT/WMwOFWBjJ1TjbKGC1j6 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/ +### +# curl 'https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/646b0de6e9f13000c9b14ba182b805312795a82a/646b0de6717e1bfa5bb44dd2a456f103c5177850?Expires=1737791001&OSSAccessKeyId=LTAI5tJJpWQEfrcKHnd1LqsZ&Signature=n7Q7BNK5Z1rFS0nDgQZxbBBpqqE%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B%20filename%3DC%2523%2520Shell%2520%2528C%2523%2520Offline%2520Compiler%2529_2.5.16.apks%3Bfilename%2A%3Dutf-8%27%27C%2523%2520Shell%2520%2528C%2523%2520Offline%2520Compiler%2529_2.5.16.apks&callback-var=eyJ4OmF1IjoiLSIsIng6dWQiOiI0LTAtNS0wLTYtTi0zLWZ0LTAtMi0wLU4iLCJ4OnNwIjoiMTAwIiwieDp0b2tlbiI6IjQtYjZlMGU5ZWUyMWFkOWZlZGIzNjMwMGY4ZWYyMWU5MjUtMi03LTE1MzYxMS1kYWNiMzY2NWJiYWE0ZjVlOWQzNzgwMGVjNjQwMzE2MC0wLTAtMC0wLTYzYmFhOGEzZGFlZGNlYzA5MmNlNzhkMDgyMmFlMjQ4IiwieDp0dGwiOiIxMDgwMCJ9&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ1ZFwiOiR7eDp1ZH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImR0X3NwXCI6JHt4OmR0X3NwfSxcImhzcFwiOiR7eDpoc3B9LFwiY2xpZW50X3Rva2VuXCI6JHtxdWVyeVN0cmluZy5jbGllbnRfdG9rZW59fSJ9&ud=4-0-5-0-6-N-3-ft-0-2-0-N' +# -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' +# -H 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8' +# -H 'Cache-Control: no-cache' +# -H 'Connection: keep-alive' +# -H 'Cookie: _UP_28A_52_=519; _UP_A4A_11_=wb9c5167d67c42ba9444ac9f42b20a05; _UP_D_=pc; __sdid=AARkEnYbifr7X5obz/wd2gzbXPw1zviyFe4xBC3uVp7xQG20ziCSbbxMib8Fov3RPRk=; __pus=9db24ba75335a2deb2e99fc400ac59ffAAQ9T+W6s02ilSvzMeh5ionWLTKFfaa2QFvJNU1PoiCYQe0aunWWq5GyJCVzXrVuICNHxooijrybFKlkUoI7xCfP; __kp=aaaeba0e-8c8e-4837-869f-882283adb802; __kps=AASxYmDMULu4nzmEK/wFzK3I; __ktd=dvy3qySVr8aXEqUuxMJydA==; __uid=AASxYmDMULu4nzmEK/wFzK3I; tfstk=gJ-IibMk8WVC79FMKXHNG51AEQSSgQi2v86JnLEUeMIdVLdF_65rKL8_2QCwYaSKtg1R6Q4UY_SeVCOMsBJeU3TgVKvkYvjrKMvhqghqgmSWKpjooOET3fJteTj5pUMeYcJhqghZgmo2KpAxkBSuFgH1XT65pgUpwGpOsTX89TEKCdCG6_IR2QptCTfOpfAThTgCtpMB-WEBJUCvp1Z8V-XCJsnc1uEJf9NVMp302uK1dwtlqg1VZw8JnZxeQ0ZGYKTOX9O-DXQMJdt5o30zYpINOKb6SXZOQa1BWHQ_euphbFOyPBGQ-6Le1ZXOW8icQI59KHLsE5ppg6sdBNoxhdQJ7HbDYfECDEvFYUdtfkOA4YqVG7kLPR_02O1qCAaurBoEyuDPFR31JOXC7AM_9UbdIO1qCAaurwBGdtksCWLl.; __puus=7a473fc40c62988cd82a0e443bb2a1baAAR498zI4bjrVRD3mNor9LX8Upgw8asjZxzEjBkb4gLBZ0tfOM5jNElFhDUmiKxA9d/xwzIgTARhY8ySH0Yl8Ipm2njsKPbk3gkplByVAZ62t0TQCe0hEdprNbdImIFDM8RbnpQ5PLvMeiJMZFJyXsK9EhAWvCpp0mO7sHVVk1oxjYkuBM3jff1l6YLQaZfd3h8=' +# -H 'DNT: 1' +# -H 'Pragma: no-cache' +# -H 'Referer: https://fast.uc.cn/' +# -H 'Sec-Fetch-Dest: iframe' +# -H 'Sec-Fetch-Mode: navigate' +# -H 'Sec-Fetch-Site: same-site' +# -H 'Sec-Fetch-User: ?1' +# -H 'Upgrade-Insecure-Requests: 1' +# -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36' +# -H 'sec-ch-ua: "Not A(Brand";v="8", "Chromium";v="132", "Google Chrome";v="132"' +# -H 'sec-ch-ua-mobile: ?0' +# -H 'sec-ch-ua-platform: "Windows"' +GET https://dl-uf-zb.pds.uc.cn/l3PNAKfz/64623447/646b0de6e9f13000c9b14ba182b805312795a82a/646b0de6717e1bfa5bb44dd2a456f103c5177850?Expires=1737791001&OSSAccessKeyId=LTAI5tJJpWQEfrcKHnd1LqsZ&Signature=n7Q7BNK5Z1rFS0nDgQZxbBBpqqE%3D&x-oss-traffic-limit=503316480&response-content-disposition=attachment%3B%20filename%3DC%2523%2520Shell%2520%2528C%2523%2520Offline%2520Compiler%2529_2.5.16.apks%3Bfilename%2A%3Dutf-8%27%27C%2523%2520Shell%2520%2528C%2523%2520Offline%2520Compiler%2529_2.5.16.apks&callback-var=eyJ4OmF1IjoiLSIsIng6dWQiOiI0LTAtNS0wLTYtTi0zLWZ0LTAtMi0wLU4iLCJ4OnNwIjoiMTAwIiwieDp0b2tlbiI6IjQtYjZlMGU5ZWUyMWFkOWZlZGIzNjMwMGY4ZWYyMWU5MjUtMi03LTE1MzYxMS1kYWNiMzY2NWJiYWE0ZjVlOWQzNzgwMGVjNjQwMzE2MC0wLTAtMC0wLTYzYmFhOGEzZGFlZGNlYzA5MmNlNzhkMDgyMmFlMjQ4IiwieDp0dGwiOiIxMDgwMCJ9&callback=eyJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb24vanNvbiIsImNhbGxiYWNrU3RhZ2UiOiJiZWZvcmUtZXhlY3V0ZSIsImNhbGxiYWNrRmFpbHVyZUFjdGlvbiI6Imlnbm9yZSIsImNhbGxiYWNrVXJsIjoiaHR0cHM6Ly9hdXRoLWNkbi51Yy5jbi9vdXRlci9vc3MvY2hlY2twbGF5IiwiY2FsbGJhY2tCb2R5Ijoie1wiaG9zdFwiOiR7aHR0cEhlYWRlci5ob3N0fSxcInNpemVcIjoke3NpemV9LFwicmFuZ2VcIjoke2h0dHBIZWFkZXIucmFuZ2V9LFwicmVmZXJlclwiOiR7aHR0cEhlYWRlci5yZWZlcmVyfSxcImNvb2tpZVwiOiR7aHR0cEhlYWRlci5jb29raWV9LFwibWV0aG9kXCI6JHtodHRwSGVhZGVyLm1ldGhvZH0sXCJpcFwiOiR7Y2xpZW50SXB9LFwicG9ydFwiOiR7Y2xpZW50UG9ydH0sXCJvYmplY3RcIjoke29iamVjdH0sXCJzcFwiOiR7eDpzcH0sXCJ1ZFwiOiR7eDp1ZH0sXCJ0b2tlblwiOiR7eDp0b2tlbn0sXCJhdVwiOiR7eDphdX0sXCJ0dGxcIjoke3g6dHRsfSxcImR0X3NwXCI6JHt4OmR0X3NwfSxcImhzcFwiOiR7eDpoc3B9LFwiY2xpZW50X3Rva2VuXCI6JHtxdWVyeVN0cmluZy5jbGllbnRfdG9rZW59fSJ9&ud=4-0-5-0-6-N-3-ft-0-2-0-N +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 +Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 +Cache-Control: no-cache +Connection: keep-alive +Cookie: _UP_28A_52_=519; _UP_A4A_11_=wb9c5167d67c42ba9444ac9f42b20a05; _UP_D_=pc; __sdid=AARkEnYbifr7X5obz/wd2gzbXPw1zviyFe4xBC3uVp7xQG20ziCSbbxMib8Fov3RPRk=; __pus=9db24ba75335a2deb2e99fc400ac59ffAAQ9T+W6s02ilSvzMeh5ionWLTKFfaa2QFvJNU1PoiCYQe0aunWWq5GyJCVzXrVuICNHxooijrybFKlkUoI7xCfP; __kp=aaaeba0e-8c8e-4837-869f-882283adb802; __kps=AASxYmDMULu4nzmEK/wFzK3I; __ktd=dvy3qySVr8aXEqUuxMJydA==; __uid=AASxYmDMULu4nzmEK/wFzK3I; tfstk=gJ-IibMk8WVC79FMKXHNG51AEQSSgQi2v86JnLEUeMIdVLdF_65rKL8_2QCwYaSKtg1R6Q4UY_SeVCOMsBJeU3TgVKvkYvjrKMvhqghqgmSWKpjooOET3fJteTj5pUMeYcJhqghZgmo2KpAxkBSuFgH1XT65pgUpwGpOsTX89TEKCdCG6_IR2QptCTfOpfAThTgCtpMB-WEBJUCvp1Z8V-XCJsnc1uEJf9NVMp302uK1dwtlqg1VZw8JnZxeQ0ZGYKTOX9O-DXQMJdt5o30zYpINOKb6SXZOQa1BWHQ_euphbFOyPBGQ-6Le1ZXOW8icQI59KHLsE5ppg6sdBNoxhdQJ7HbDYfECDEvFYUdtfkOA4YqVG7kLPR_02O1qCAaurBoEyuDPFR31JOXC7AM_9UbdIO1qCAaurwBGdtksCWLl.; +Pragma: no-cache +Referer: https://fast.uc.cn/ + +### + +# curl 'https://fast-api.uc.cn/1/transfer/member?fr=pc&pr=UCBrowser&fetch_rights=ALL' +# -H 'accept: application/json, text/plain, */*' +# -H 'accept-language: zh-CN,zh;q=0.9' +# -H 'cache-control: no-cache' +# -H 'cookie: __pus=52e1ead14f116cf7c9e1f661e94cd253AAT2jmfclZedBkubcvIXwKTFo7XJmjaf4bHgaMR/vSLdC1iXn192H+d3SgVIFkiWWjUAlSInoboPn7Zg5KU1Cbis; __kp=ac118c62-20c1-4e12-aac1-d901f6a0e8d4; __kps=AASxYmDMULu4nzmEK/wFzK3I; __ktd=dvy3qySVr8aXEqUuxMJydA==; __uid=AASxYmDMULu4nzmEK/wFzK3I; XSRF-TOKEN=67412de4-5552-4f80-aca5-a4e23ac2621a; XSRF-TOKEN=67412de4-5552-4f80-aca5-a4e23ac2621a; __puus=b2c6f59b3607030fb60c1d486ca09126AAR498zI4bjrVRD3mNor9LX86VT5PSEpFI0gt/S1i/S8HStTB8LEW+gpFt7z2zsuZDcCgcxzWFAPKQXYedkkQ03+iTFqCGSScL0iSNCfE1+aqsf7fkE2ToXKz+zHxg3iVTYNaSnUCkbXk6QlMPaatHGJeHuh0RpS7lG75zREt1MArKS0wWYF5hCgYogvvp92tkQ=' +# -H 'dnt: 1' +# -H 'origin: https://fast.uc.cn' +# -H 'pragma: no-cache' +# -H 'priority: u=1, i' +# -H 'referer: https://fast.uc.cn/' +# -H 'sec-ch-ua: "Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"' +# -H 'sec-ch-ua-mobile: ?0' +# -H 'sec-ch-ua-platform: "Windows"' +# -H 'sec-fetch-dest: empty' +# -H 'sec-fetch-mode: cors' +# -H 'sec-fetch-site: same-site' +# -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0' +# -H 'x-biz-retry: 0' +GET https://fast-api.uc.cn/1/transfer/member?fr=pc&pr=UCBrowser&fetch_rights=ALL +accept: application/json, text/plain, */* +accept-language: zh-CN,zh;q=0.9 +cache-control: no-cache +cookie: __pus=52e1ead14f116cf7c9e1f661e94cd253AAT2jmfclZedBkubcvIXwKTFo7XJmjaf4bHgaMR/vSLdC1iXn192H+d3SgVIFkiWWjUAlSInoboPn7Zg5KU1Cbis; +dnt: 1 +### +# curl 'https://fast.uc.cn/api/info?fr=pc&pr=UCBrowser' +# -H 'accept: application/json, text/plain, */*' +# -H 'accept-language: zh-CN,zh;q=0.9' +# -H 'cache-control: no-cache' +# -H 'content-type: application/json' +# -H 'cookie: UDRIVE_TRANSFER_SESS=PjvNRi7KTc55QvE9cxLKQKTWRNH_9C8dTVuWdgOJm9eKVLxXZy7_bXk92ma8wNw9XIOlqhtVTZ8BXNkV4jbTQjYjTrG8Z0FqcE_PMPDsctcmnxujbLa1jnm7SpVB2i3i-fltzwwwoI9RhkkfLZVMW3_cw2llA6Yip847Pr-auhXC-ZJpNp3nzPLANTgn19lz; b-user-id=d3b7a19e-c576-0fb1-602a-e3cf7821d90e' +# -H 'dnt: 1' +# -H 'origin: https://fast.uc.cn' +# -H 'pragma: no-cache' +# -H 'priority: u=1, i' +# -H 'referer: https://fast.uc.cn/s/33197dd53ace4' +# -H 'sec-ch-ua: "Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"' +# -H 'sec-ch-ua-mobile: ?0' +# -H 'sec-ch-ua-platform: "Windows"' +# -H 'sec-fetch-dest: empty' +# -H 'sec-fetch-mode: cors' +# -H 'sec-fetch-site: same-origin' +# -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0' +# -H 'x-biz-retry: 0' +# --data-raw '{"st":"st9c5631ad6j032w5rdr0978zxcl1qjt"}' +# 不限跨域 +POST https://fast.uc.cn/api/info?fr=pc&pr=UCBrowser +accept: application/json, text/plain, */* +accept-language: zh-CN,zh;q=0.9 +cache-control: no-cache +cookie: UDRIVE_TRANSFER_SESS=PjvNRi7KTc55QvE9cxLKQKTWRNH_9C8dTVuWdgOJm9eKVLxXZy7_bXk92ma8wNw9XIOlqhtVTZ8BXNkV4jbTQjYjTrG8Z0FqcE_PMPDsctcmnxujbLa1jnm7SpVB2i3i-fltzwwwoI9RhkkfLZVMW3_cw2llA6Yip847Pr-auhXC-ZJpNp3nzPLANTgn19lz; b-user-id=d3b7a19e-c576-0fb1-602a-e3cf7821d90e +dnt: 1 +origin: https://fast.qqq.cn +pragma: no-cache +priority: u=1, i +referer: https://fast.qqq.cn/s/33197dd53ace4 +sec-ch-ua: "Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132" +sec-ch-ua-mobile: ?0 +sec-ch-ua-platform: "Windows" +sec-fetch-dest: empty +sec-fetch-mode: cors +sec-fetch-site: same-origin +user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0 +x-biz-retry: 0 +Content-Type: application/json + +{ + "st": "xx" +} + +### + + +wx -> st -> pus->puus + +pus-> st + /info +https://fast-api.uc.cn/1/transfer/member puus +###