feat: 添加捐赠账号功能,支持数据库存储和随机选择账号解析

This commit is contained in:
rensumo
2026-02-19 12:59:47 +08:00
parent d06974d556
commit 04443bcb5e
5 changed files with 417 additions and 13 deletions

View File

@@ -477,4 +477,32 @@ public class ParserApi {
ClientLinkType type = ClientLinkType.valueOf(clientType.toUpperCase());
return clientLinks.get(type);
}
// ========== 捐赠账号 API ==========
/**
* 捐赠网盘账号
*/
@RouteMapping(value = "/donateAccount", method = RouteMethod.POST)
public Future<JsonObject> donateAccount(HttpServerRequest request, JsonObject body) {
String ip = request.remoteAddress().host();
body.put("ip", ip);
return dbService.saveDonatedAccount(body);
}
/**
* 获取各网盘捐赠账号数量
*/
@RouteMapping(value = "/donateAccountCounts", method = RouteMethod.GET)
public Future<JsonObject> getDonateAccountCounts() {
return dbService.getDonatedAccountCounts();
}
/**
* 随机获取指定网盘类型的捐赠账号(内部使用,返回加密后的 auth 参数)
*/
@RouteMapping(value = "/randomAuth", method = RouteMethod.GET)
public Future<JsonObject> getRandomAuth(String panType) {
return dbService.getRandomDonatedAccount(panType);
}
}

View File

@@ -0,0 +1,52 @@
package cn.qaiu.lz.web.model;
import cn.qaiu.db.ddl.Constraint;
import cn.qaiu.db.ddl.Length;
import cn.qaiu.db.ddl.Table;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* 捐赠账号实体
* 用户捐赠的网盘认证信息,解析时随机选择使用
*/
@Data
@Table("donated_account")
public class DonatedAccount {
private static final long serialVersionUID = 1L;
@Constraint(autoIncrement = true, notNull = true)
private Long id;
@Length(varcharSize = 16)
@Constraint(notNull = true)
private String panType; // 网盘类型: QK, UC, FJ, IZ, YE
@Length(varcharSize = 32)
@Constraint(notNull = true)
private String authType; // 认证类型: cookie, accesstoken, authorization, password, custom
@Length(varcharSize = 128)
private String username; // 用户名
@Length(varcharSize = 128)
private String password; // 密码
@Length(varcharSize = 4096)
private String token; // Cookie/Token
@Length(varcharSize = 64)
private String remark; // 备注
@Length(varcharSize = 64)
private String ip; // 捐赠者IP
@Constraint(notNull = true, defaultValue = "true")
private Boolean enabled = true; // 是否启用
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime = new Date();
}

View File

@@ -50,4 +50,21 @@ public interface DbService extends BaseAsyncService {
*/
Future<JsonObject> getPlaygroundParserById(Long id);
// ========== 捐赠账号相关 ==========
/**
* 保存捐赠账号
*/
Future<JsonObject> saveDonatedAccount(JsonObject account);
/**
* 获取各网盘捐赠账号数量统计
*/
Future<JsonObject> getDonatedAccountCounts();
/**
* 随机获取指定网盘类型的一个启用账号
*/
Future<JsonObject> getRandomDonatedAccount(String panType);
}

View File

@@ -265,4 +265,94 @@ public class DbServiceImpl implements DbService {
return promise.future();
}
// ========== 捐赠账号相关 ==========
@Override
public Future<JsonObject> saveDonatedAccount(JsonObject account) {
JDBCPool client = JDBCPoolInit.instance().getPool();
Promise<JsonObject> promise = Promise.promise();
String sql = """
INSERT INTO donated_account
(pan_type, auth_type, username, password, token, remark, ip, enabled, create_time)
VALUES (?, ?, ?, ?, ?, ?, ?, true, NOW())
""";
client.preparedQuery(sql)
.execute(Tuple.of(
account.getString("panType"),
account.getString("authType"),
account.getString("username"),
account.getString("password"),
account.getString("token"),
account.getString("remark"),
account.getString("ip")
))
.onSuccess(res -> {
promise.complete(JsonResult.success("捐赠成功").toJsonObject());
})
.onFailure(e -> {
log.error("saveDonatedAccount failed", e);
promise.fail(e);
});
return promise.future();
}
@Override
public Future<JsonObject> getDonatedAccountCounts() {
JDBCPool client = JDBCPoolInit.instance().getPool();
Promise<JsonObject> promise = Promise.promise();
String sql = "SELECT pan_type, COUNT(*) as count FROM donated_account WHERE enabled = true GROUP BY pan_type";
client.query(sql).execute().onSuccess(rows -> {
JsonObject counts = new JsonObject();
int total = 0;
for (Row row : rows) {
String panType = row.getString("pan_type");
Integer count = row.getInteger("count");
counts.put(panType, count);
total += count;
}
counts.put("total", total);
promise.complete(JsonResult.data(counts).toJsonObject());
}).onFailure(e -> {
log.error("getDonatedAccountCounts failed", e);
promise.fail(e);
});
return promise.future();
}
@Override
public Future<JsonObject> getRandomDonatedAccount(String panType) {
JDBCPool client = JDBCPoolInit.instance().getPool();
Promise<JsonObject> promise = Promise.promise();
String sql = "SELECT * FROM donated_account WHERE pan_type = ? AND enabled = true ORDER BY RAND() LIMIT 1";
client.preparedQuery(sql)
.execute(Tuple.of(panType))
.onSuccess(rows -> {
if (rows.size() > 0) {
Row row = rows.iterator().next();
JsonObject account = new JsonObject();
account.put("authType", row.getString("auth_type"));
account.put("username", row.getString("username"));
account.put("password", row.getString("password"));
account.put("token", row.getString("token"));
promise.complete(JsonResult.data(account).toJsonObject());
} else {
promise.complete(JsonResult.data(new JsonObject()).toJsonObject());
}
})
.onFailure(e -> {
log.error("getRandomDonatedAccount failed", e);
promise.fail(e);
});
return promise.future();
}
}