增加tracker转发
Change-Id: I5aad9b143371870714b49040708170f578f7df89
diff --git a/front/package-lock.json b/front/package-lock.json
index 2277d88..2fc8ceb 100644
--- a/front/package-lock.json
+++ b/front/package-lock.json
@@ -16884,9 +16884,9 @@
}
},
"node_modules/typescript": {
- "version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+ "version": "4.9.5",
+ "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"license": "Apache-2.0",
"peer": true,
"bin": {
@@ -16894,7 +16894,7 @@
"tsserver": "bin/tsserver"
},
"engines": {
- "node": ">=14.17"
+ "node": ">=4.2.0"
}
},
"node_modules/unbox-primitive": {
diff --git a/pom.xml b/pom.xml
index 34a5ced..f93819e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,10 +13,21 @@
<properties>
<!-- 使用 Java 9,以支持接口中的 private 方法 -->
<maven.compiler.source>9</maven.compiler.source>
+ <maven.compiler.target>9</maven.compiler.target>
<!-- 如果还没定义,请添加 QueryDSL 版本 -->
<querydsl.version>5.0.0</querydsl.version>
</properties>
+ <!-- 不再需要额外的 simpleframework 仓库,所有依赖均可从 Central 获取 -->
+ <!--
+ <repositories>
+ <repository>
+ <id>simpleframework-releases</id>
+ <url>https://repo.simpleframework.org/releases/</url>
+ </repository>
+ </repositories>
+ -->
+
<!-- 添加依赖 -->
<dependencies>
<!-- Apache Commons Lang3,用于 Pair 等工具类 -->
@@ -25,26 +36,31 @@
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
+
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
+
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.6.14.Final</version>
</dependency>
+
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
+
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
+
<!-- QueryDSL -->
<dependency>
<groupId>com.querydsl</groupId>
@@ -57,11 +73,13 @@
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
+
<!-- JUnit Jupiter API & Engine for writing and running tests -->
<dependency>
<groupId>org.junit.jupiter</groupId>
@@ -76,13 +94,15 @@
<version>5.9.1</version>
<scope>test</scope>
</dependency>
- <!-- 添加 Querydsl 核心依赖 -->
+
+ <!-- 添加 QueryDSL 核心依赖 -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>5.0.0</version>
</dependency>
- <!-- 添加 Querydsl APT,仅在编译时使用 -->
+
+ <!-- 添加 QueryDSL APT,仅在编译时使用 -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
@@ -95,6 +115,13 @@
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.6</version> <!-- 根据需要调整版本 -->
</dependency>
+
+ <!-- SimpleFramework 整合包,5.1.6 版本可从 Maven Central 拉取,包含 HTTP 与 Transport 模块 -->
+ <dependency>
+ <groupId>org.simpleframework</groupId>
+ <artifactId>simple</artifactId>
+ <version>5.1.6</version>
+ </dependency>
</dependencies>
<!-- 构建配置 -->
@@ -137,6 +164,7 @@
<generatedSourcesDirectory>${project.build.directory}/generated-sources/java</generatedSourcesDirectory>
</configuration>
</plugin>
+
<!-- 执行插件,方便 mvn exec:java 直接运行 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
@@ -146,6 +174,8 @@
<mainClass>api.ApiMain</mainClass>
</configuration>
</plugin>
+
+ <!-- QueryDSL APT 插件,用于生成 Q 类 -->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
@@ -162,6 +192,8 @@
</execution>
</executions>
</plugin>
+
+ <!-- Surefire 插件,用于运行单元测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@@ -176,12 +208,14 @@
</configuration>
</plugin>
+ <!-- Spring Boot Maven 插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.6</version>
</plugin>
- <!-- Optional: 将生成目录加入编译生命周期 -->
+
+ <!-- 将生成目录加入编译生命周期 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
@@ -201,25 +235,7 @@
</execution>
</executions>
</plugin>
- <!-- 添加 APT 插件配置,生成 Q 类 -->
- <plugin>
- <groupId>com.mysema.maven</groupId>
- <artifactId>apt-maven-plugin</artifactId>
- <version>1.1.3</version>
- <executions>
- <execution>
- <goals>
- <goal>process</goal>
- </goals>
- <configuration>
- <!-- 生成目录,可根据项目实际调整 -->
- <outputDirectory>target/generated-sources/java</outputDirectory>
- <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
-</project>
\ No newline at end of file
+</project>
diff --git a/src/main/java/api/ApiApplication.java b/src/main/java/api/ApiApplication.java
index 6d65a81..1f39e69 100644
--- a/src/main/java/api/ApiApplication.java
+++ b/src/main/java/api/ApiApplication.java
@@ -2,10 +2,18 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import tracker.DataCaptureServer;
+import java.io.IOException;
@SpringBootApplication
public class ApiApplication {
public static void main(String[] args) {
+
+ try{
+ DataCaptureServer.start();
+ }catch(IOException e){
+ System.out.println(e);
+ }
SpringApplication.run(ApiApplication.class, args);
}
diff --git a/src/main/java/entity/config.java b/src/main/java/entity/config.java
index ec4ab2e..07fbced 100644
--- a/src/main/java/entity/config.java
+++ b/src/main/java/entity/config.java
@@ -13,4 +13,7 @@
public static final String SqlPassword = "123456";
public static final String SqlUsername = "root";
public static final String TORRENT_STORAGE_DIR = "torrents";
+ public static final String trackerHost="0.0.0.0";
+ public static final int trackerPort=6969;
+ public static final int capturePort=6970;
}
diff --git a/src/main/java/tracker/DataCaptureProxy.java b/src/main/java/tracker/DataCaptureProxy.java
new file mode 100644
index 0000000..4d2737f
--- /dev/null
+++ b/src/main/java/tracker/DataCaptureProxy.java
@@ -0,0 +1,73 @@
+package tracker;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.simpleframework.http.Request;
+import org.simpleframework.http.Response;
+import org.simpleframework.http.core.Container;
+
+/**
+ * 拦截 announce 请求,打印参数后转发给真实 Tracker。
+ */
+public class DataCaptureProxy implements Container {
+
+ private final String trackerHost;
+ private final int trackerPort;
+
+ public DataCaptureProxy(String trackerHost, int trackerPort) {
+ this.trackerHost = trackerHost;
+ this.trackerPort = trackerPort;
+ }
+
+ @Override
+ public void handle(Request req, Response resp) {
+ try {
+ // 提取并打印关键参数
+ String infoHash = req.getParameter("info_hash");
+ String uploaded = req.getParameter("uploaded");
+ String downloaded= req.getParameter("downloaded");
+ String passkey = req.getParameter("passkey");
+ System.out.println(
+ "Captured announce → info_hash=" + infoHash +
+ ", uploaded=" + uploaded +
+ ", downloaded=" + downloaded +
+ ", passkey=" + passkey
+ );
+
+ // 构造转发 URL
+ String path = req.getPath().getPath();
+ String query = req.getQuery().toString();
+ String targetUrl = "http://" + trackerHost + ":" + trackerPort
+ + path + "?" + query;
+
+ HttpURLConnection connection =
+ (HttpURLConnection) new URL(targetUrl).openConnection();
+ connection.setRequestMethod("GET");
+
+ // 转发响应码和类型
+ resp.setCode(connection.getResponseCode());
+ String ct = connection.getContentType();
+ if (ct != null) resp.setValue("Content-Type", ct);
+
+ // 转发响应体
+ try (InputStream in = connection.getInputStream();
+ OutputStream out = resp.getOutputStream()) {
+ byte[] buf = new byte[8192];
+ int len;
+ while ((len = in.read(buf)) != -1) {
+ out.write(buf, 0, len);
+ }
+ }
+
+ } catch (Exception e) {
+ try {
+ resp.setCode(500);
+ resp.close();
+ } catch (Exception ignore) {}
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/tracker/DataCaptureServer.java b/src/main/java/tracker/DataCaptureServer.java
new file mode 100644
index 0000000..57ce8d0
--- /dev/null
+++ b/src/main/java/tracker/DataCaptureServer.java
@@ -0,0 +1,33 @@
+package tracker;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.simpleframework.http.core.ContainerServer;
+import org.simpleframework.transport.connect.Connection;
+import org.simpleframework.transport.connect.SocketConnection;
+
+import entity.config;
+
+/**
+ * 启动 DataCaptureProxy:
+ * 客户端将 announce 请求发到本机 capturePort,
+ * 由 DataCaptureProxy 拦截并转发到 trackerHost:trackerPort。
+ */
+public class DataCaptureServer {
+
+ public static void start() throws IOException {
+ String trackerHost = config.trackerHost;
+ int trackerPort = config.trackerPort;
+ int capturePort = config.capturePort;
+
+ DataCaptureProxy proxy = new DataCaptureProxy(trackerHost, trackerPort);
+ ContainerServer server = new ContainerServer(proxy);
+ Connection conn = new SocketConnection(server);
+
+ conn.connect(new InetSocketAddress(capturePort));
+ System.out.println("DataCapture proxy listening on port "
+ + capturePort + ", forwarding to "
+ + trackerHost + ":" + trackerPort);
+ }
+}
diff --git a/testdata.sql b/testdata.sql
new file mode 100644
index 0000000..c1ad1e7
--- /dev/null
+++ b/testdata.sql
@@ -0,0 +1,514 @@
+-- MySQL dump 10.13 Distrib 8.0.42, for Linux (x86_64)
+--
+-- Host: localhost Database: pt_database_test
+-- ------------------------------------------------------
+-- Server version 8.0.42-0ubuntu0.24.04.1
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `Announcement`
+--
+
+DROP TABLE IF EXISTS `Announcement`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `Announcement` (
+ `announce_id` varchar(64) NOT NULL,
+ `content` text NOT NULL,
+ `is_public` tinyint(1) NOT NULL DEFAULT '0',
+ `tag` varchar(100) DEFAULT NULL,
+ PRIMARY KEY (`announce_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `Announcement`
+--
+
+LOCK TABLES `Announcement` WRITE;
+/*!40000 ALTER TABLE `Announcement` DISABLE KEYS */;
+INSERT INTO `Announcement` VALUES ('a1b2c3d4-e5f6-4711-89ab-cdef01234567','系统升级将在今晚 23:00 开始,预计持续 2 小时,期间可能无法访问。',1,'系统通知'),('a7b8c9d0-e1f2-4d77-ef01-23456789abcd','新增帮助中心文章:如何重置密码以及常见问题解答。',1,'帮助文档'),('b2c3d4e5-f6a7-4822-9abc-def012345678','新版本发布:增加了用户头像上传功能和消息提醒。',1,'产品更新'),('b8c9d0e1-f2a3-4e88-f012-3456789abcde','安全提醒:请尽快启用双因素认证,保障账户安全。',1,'安全提醒'),('c3d4e5f6-a7b8-4933-abcd-ef0123456789','本周末例行数据库维护,可能会短暂影响服务稳定性。',0,'运维公告'),('c9d0e1f2-a3b4-4f99-0123-456789abcdef','服务器证书将于 6 月 15 日过期,请相关负责人及时更新。',0,'运维公告'),('d0e1f2a3-b4c5-4a10-1234-56789abcdef0','本月员工生日会定于 5 月 30 日举办,地点:公司大会议室。',1,'公司活动'),('d4e5f6a7-b8c9-4a44-bcde-f0123456789a','节假日放假通知:5 月 1 日—5 月 3 日放假,共 3 天。',1,'节假日'),('e5f6a7b8-c9d0-4b55-cdef-0123456789ab','用户调查问卷已上线,欢迎参与并反馈使用感受。',1,'用户调研'),('f6a7b8c9-d0e1-4c66-def0-123456789abc','API 接口将于下周三变更,旧版接口将在 6 月底下线。',0,'开发者公告');
+/*!40000 ALTER TABLE `Announcement` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Appeal`
+--
+
+DROP TABLE IF EXISTS `Appeal`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `Appeal` (
+ `appeal_id` varchar(64) NOT NULL COMMENT '申诉ID',
+ `user_id` varchar(36) NOT NULL COMMENT '申诉人(User.user_id)',
+ `content` text NOT NULL COMMENT '申诉内容',
+ `file_url` varchar(255) DEFAULT NULL COMMENT '申诉文件URL',
+ `status` int NOT NULL DEFAULT '0' COMMENT '审核状态',
+ PRIMARY KEY (`appeal_id`),
+ KEY `fk_appeal_user` (`user_id`),
+ CONSTRAINT `fk_appeal_user` FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='申诉表,记录用户的申诉信息';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `Appeal`
+--
+
+LOCK TABLES `Appeal` WRITE;
+/*!40000 ALTER TABLE `Appeal` DISABLE KEYS */;
+INSERT INTO `Appeal` VALUES ('0307ad3c-09b5-40c0-8aa3-c5a8f0178f4c','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 9','http://example.com/file9',0),('202dd30a-3ee7-4d0f-a227-0a17325c9c68','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 8','http://example.com/file8',0),('212d0782-2ccb-4f25-876d-d4be990af7bc','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 6','http://example.com/file6',0),('4995a460-128e-4886-8682-e75bbb2dbce2','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 1','http://example.com/file1',0),('7b9c4044-39b6-41b5-8754-ff784788f116','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 2','http://example.com/file2',0),('a38fa86d-9bce-4342-852d-272566e46553','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 3','http://example.com/file3',0),('a6345f31-6938-4ff9-8c1e-0f5b3c9d6d56','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 5','http://example.com/file5',0),('b1c3fcdd-6c25-42d2-9782-cae4bd609368','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 0','http://example.com/file0',0),('bef4085a-1ec3-40ea-a43c-1964c9180e9d','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 7','http://example.com/file7',0),('ce843f31-eb01-4954-a234-d175d262bfdc','550e8400-e29b-41d4-a716-446655440000','GetAppealList test content 4','http://example.com/file4',0);
+/*!40000 ALTER TABLE `Appeal` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `BegSeed`
+--
+
+DROP TABLE IF EXISTS `BegSeed`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `BegSeed` (
+ `beg_id` varchar(64) NOT NULL,
+ `beg_count` int NOT NULL DEFAULT '0',
+ `reward_magic` int NOT NULL DEFAULT '0',
+ `deadline` datetime NOT NULL,
+ `has_match` tinyint(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`beg_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `BegSeed`
+--
+
+LOCK TABLES `BegSeed` WRITE;
+/*!40000 ALTER TABLE `BegSeed` DISABLE KEYS */;
+INSERT INTO `BegSeed` VALUES ('test_beg_settle_1749112257693',1,100,'2025-05-21 08:30:58',1),('test_beg_settle_1749113033612',1,100,'2025-05-21 08:43:54',1),('test_beg_settle_1749115170790',1,100,'2025-05-21 09:19:31',1);
+/*!40000 ALTER TABLE `BegSeed` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Post`
+--
+
+DROP TABLE IF EXISTS `Post`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `Post` (
+ `post_id` varchar(64) NOT NULL,
+ `title` varchar(255) NOT NULL,
+ `content` text NOT NULL,
+ `author_id` varchar(36) NOT NULL,
+ `created_at` datetime NOT NULL,
+ `reply_count` int NOT NULL DEFAULT '0',
+ `view_count` int NOT NULL DEFAULT '0',
+ PRIMARY KEY (`post_id`),
+ KEY `fk_post_user` (`author_id`),
+ CONSTRAINT `fk_post_user` FOREIGN KEY (`author_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `Post`
+--
+
+LOCK TABLES `Post` WRITE;
+/*!40000 ALTER TABLE `Post` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Post` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `PostReply`
+--
+
+DROP TABLE IF EXISTS `PostReply`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `PostReply` (
+ `reply_id` varchar(64) NOT NULL,
+ `post_id` varchar(64) NOT NULL,
+ `content` text NOT NULL,
+ `author_id` varchar(36) NOT NULL,
+ `created_at` datetime NOT NULL,
+ PRIMARY KEY (`reply_id`),
+ KEY `fk_pr_post` (`post_id`),
+ KEY `fk_pr_user` (`author_id`),
+ CONSTRAINT `fk_pr_post` FOREIGN KEY (`post_id`) REFERENCES `Post` (`post_id`) ON DELETE CASCADE,
+ CONSTRAINT `fk_pr_user` FOREIGN KEY (`author_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `PostReply`
+--
+
+LOCK TABLES `PostReply` WRITE;
+/*!40000 ALTER TABLE `PostReply` DISABLE KEYS */;
+/*!40000 ALTER TABLE `PostReply` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Seed`
+--
+
+DROP TABLE IF EXISTS `Seed`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `Seed` (
+ `seed_id` varchar(64) NOT NULL,
+ `owner_user_id` varchar(36) NOT NULL,
+ `fake_hits` int NOT NULL DEFAULT '0',
+ `last_fake_check` datetime DEFAULT NULL,
+ `external_url` varchar(255) DEFAULT NULL,
+ `title` varchar(255) NOT NULL,
+ `subtitle` varchar(255) DEFAULT NULL,
+ `size` varchar(50) NOT NULL,
+ `tags` varchar(255) DEFAULT NULL,
+ `popularity` int NOT NULL DEFAULT '0',
+ `URL` text COMMENT 'TTorrent 文件在服务器上存储的 URL',
+ PRIMARY KEY (`seed_id`),
+ KEY `fk_seed_user` (`owner_user_id`),
+ CONSTRAINT `fk_seed_user` FOREIGN KEY (`owner_user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `Seed`
+--
+
+LOCK TABLES `Seed` WRITE;
+/*!40000 ALTER TABLE `Seed` DISABLE KEYS */;
+INSERT INTO `Seed` VALUES ('exampleSeedId','550e8400-e29b-41d4-a716-446655440000',0,NULL,NULL,'test',NULL,'1GB','大陆',0,'torrents/exampleSeedId_exampleSeedId_test16436511100052430070.torrent'),('seed001','550e8400-e29b-41d4-a716-446655440000',10,'2025-05-19 10:00:00','http://example.com/seed001','Awesome Movie','Action Thriller','1.5GB','大陆',100,'torrents/seed001_seed001_test17718681796068962628.torrent'),('seed004','550e8400-e29b-41d4-a716-446655440003',8,'2025-05-19 11:00:00','http://example.com/seed004','Comedy Series','Season 1','700MB','大陆',75,'torrents/seed004_seed004_test2953554280018110244.torrent'),('seed009','550e8400-e29b-41d4-a716-446655440008',18,'2025-05-17 21:45:00','http://example.com/seed009','Sci-Fi Movie','Space Odyssey','2GB','港台',180,'torrents/seed009_seed009_test13451296490325930642.torrent'),('seed111','550e8400-e29b-41d4-a716-446655440003',0,NULL,NULL,'test2',NULL,'1',NULL,0,'torrents/seed111_seed111_test14021531522609506819.torrent'),('seed222','550e8400-e29b-41d4-a716-446655440003',0,NULL,NULL,'test3',NULL,'1','港剧',0,'torrents/seed222_seed222_test11259979984170882790.torrent'),('test_seed_settle_1749111508968','550e8400-e29b-41d4-a716-446655440000',0,NULL,NULL,'测试种子',NULL,'1',NULL,0,'torrents/test_seed_settle_1749111508968_test_seed_settle_1749111508968_test14644621044707116370.torrent'),('test_seed_settle_1749111581741','550e8400-e29b-41d4-a716-446655440000',0,NULL,NULL,'测试种子',NULL,'1',NULL,0,'torrents/test_seed_settle_1749111581741_test_seed_settle_1749111581741_test4953741892853909459.torrent'),('test_seed_settle_1749112208219','550e8400-e29b-41d4-a716-446655440000',0,NULL,NULL,'测试种子',NULL,'1',NULL,0,'torrents/test_seed_settle_1749112208219_test_seed_settle_1749112208219_test3659044688757063978.torrent'),('test_seed_settle_1749112257695','550e8400-e29b-41d4-a716-446655440000',0,NULL,NULL,'测试种子',NULL,'1',NULL,0,'torrents/test_seed_settle_1749112257695_test_seed_settle_1749112257695_test17979750181307660047.torrent'),('test_seed_settle_1749113033614','550e8400-e29b-41d4-a716-446655440000',0,NULL,NULL,'测试种子',NULL,'1',NULL,0,'torrents/test_seed_settle_1749113033614_test_seed_settle_1749113033614_test13945890241269543288.torrent'),('test_seed_settle_1749115170791','550e8400-e29b-41d4-a716-446655440000',0,NULL,NULL,'测试种子',NULL,'1',NULL,0,NULL);
+/*!40000 ALTER TABLE `Seed` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `SeedDownload`
+--
+
+DROP TABLE IF EXISTS `SeedDownload`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `SeedDownload` (
+ `task_id` varchar(64) NOT NULL,
+ `user_id` varchar(36) NOT NULL,
+ `seed_id` varchar(64) NOT NULL,
+ `download_start` datetime NOT NULL,
+ `download_end` datetime DEFAULT NULL,
+ `is_dedicated` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0=普通,1=专线',
+ `client_ip` varchar(45) DEFAULT NULL,
+ PRIMARY KEY (`task_id`),
+ KEY `fk_sd_user` (`user_id`),
+ KEY `fk_sd_seed` (`seed_id`),
+ CONSTRAINT `fk_sd_seed` FOREIGN KEY (`seed_id`) REFERENCES `Seed` (`seed_id`) ON DELETE CASCADE,
+ CONSTRAINT `fk_sd_user` FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `SeedDownload`
+--
+
+LOCK TABLES `SeedDownload` WRITE;
+/*!40000 ALTER TABLE `SeedDownload` DISABLE KEYS */;
+INSERT INTO `SeedDownload` VALUES ('3717648a-3ac0-11f0-b2ca-bc2411405807','550e8400-e29b-41d4-a716-446655440000','seed001','2025-05-01 09:12:34','2025-05-01 09:15:02',1,NULL),('3717762c-3ac0-11f0-b2ca-bc2411405807','550e8400-e29b-41d4-a716-446655440003','seed004','2025-05-04 07:30:10','2025-05-04 07:35:55',1,NULL),('3717806c-3ac0-11f0-b2ca-bc2411405807','550e8400-e29b-41d4-a716-446655440008','seed009','2025-05-09 05:05:05',NULL,0,NULL);
+/*!40000 ALTER TABLE `SeedDownload` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `SubmitSeed`
+--
+
+DROP TABLE IF EXISTS `SubmitSeed`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `SubmitSeed` (
+ `beg_id` varchar(64) NOT NULL,
+ `seed_id` varchar(64) NOT NULL,
+ `votes` int NOT NULL DEFAULT '0',
+ PRIMARY KEY (`beg_id`,`seed_id`),
+ KEY `fk_ss_seed` (`seed_id`),
+ CONSTRAINT `fk_ss_beg` FOREIGN KEY (`beg_id`) REFERENCES `BegSeed` (`beg_id`) ON DELETE CASCADE,
+ CONSTRAINT `fk_ss_seed` FOREIGN KEY (`seed_id`) REFERENCES `Seed` (`seed_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `SubmitSeed`
+--
+
+LOCK TABLES `SubmitSeed` WRITE;
+/*!40000 ALTER TABLE `SubmitSeed` DISABLE KEYS */;
+INSERT INTO `SubmitSeed` VALUES ('test_beg_settle_1749112257693','test_seed_settle_1749112257695',1),('test_beg_settle_1749113033612','test_seed_settle_1749113033614',1),('test_beg_settle_1749115170790','test_seed_settle_1749115170791',1);
+/*!40000 ALTER TABLE `SubmitSeed` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Transport`
+--
+
+DROP TABLE IF EXISTS `Transport`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `Transport` (
+ `task_id` varchar(64) NOT NULL,
+ `uploader_id` varchar(36) NOT NULL,
+ `downloader_id` varchar(36) NOT NULL,
+ `seed_id` varchar(64) NOT NULL,
+ `uploaded` bigint NOT NULL DEFAULT '0',
+ `downloaded` bigint NOT NULL DEFAULT '0',
+ `upload_peak` bigint NOT NULL DEFAULT '0',
+ `download_peak` bigint NOT NULL DEFAULT '0',
+ PRIMARY KEY (`task_id`,`uploader_id`,`downloader_id`),
+ KEY `fk_tr_user_up` (`uploader_id`),
+ KEY `fk_tr_user_down` (`downloader_id`),
+ KEY `fk_tr_seed` (`seed_id`),
+ CONSTRAINT `fk_tr_seed` FOREIGN KEY (`seed_id`) REFERENCES `Seed` (`seed_id`) ON DELETE CASCADE,
+ CONSTRAINT `fk_tr_user_down` FOREIGN KEY (`downloader_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `fk_tr_user_up` FOREIGN KEY (`uploader_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `Transport`
+--
+
+LOCK TABLES `Transport` WRITE;
+/*!40000 ALTER TABLE `Transport` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Transport` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `User`
+--
+
+DROP TABLE IF EXISTS `User`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `User` (
+ `user_id` varchar(36) NOT NULL,
+ `email` varchar(255) NOT NULL,
+ `username` varchar(100) NOT NULL,
+ `password` varchar(255) NOT NULL,
+ `gender` enum('m','f') NOT NULL,
+ `school` varchar(255) DEFAULT NULL,
+ `avatar_url` varchar(255) DEFAULT NULL,
+ `bio` text,
+ `account_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0=正常,1=被ban',
+ `invite_left` int NOT NULL DEFAULT '0',
+ `detectedCount` int NOT NULL DEFAULT '0',
+ `lastDetectedTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `fake_detected_count` int NOT NULL DEFAULT '0',
+ `fake_last_detected_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`user_id`,`email`),
+ UNIQUE KEY `uniq_email` (`email`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `User`
+--
+
+LOCK TABLES `User` WRITE;
+/*!40000 ALTER TABLE `User` DISABLE KEYS */;
+INSERT INTO `User` VALUES ('550e8400-e29b-41d4-a716-446655440000','alice@example.com','alice','$2y$10$abcdefghijklmnopqrstuv','f','Stanford University','https://cdn.example.com/avatars/alice.jpg','Passionate swimmer and coder.',0,5,0,'2025-05-20 12:29:40',0,'2025-05-27 09:37:46'),('550e8400-e29b-41d4-a716-446655440003','dave@example.net','dave','$2y$10$mnopqrstuvwxyzABCDEF','m','University of Oxford','https://cdn.example.com/avatars/dave.jpg','Guitarist in a jazz band.',0,0,0,'2025-05-20 12:29:40',0,'2025-05-27 09:37:46'),('550e8400-e29b-41d4-a716-446655440008','irene@example.org','irene','$2y$10$34567890abcdefghijklmn','f','National University of Singapore','https://cdn.example.com/avatars/irene.jpg','Time-lapse photographer and traveler.',0,0,0,'2025-05-20 12:29:40',0,'2025-05-27 09:37:46');
+/*!40000 ALTER TABLE `User` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `UserFavorite`
+--
+
+DROP TABLE IF EXISTS `UserFavorite`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `UserFavorite` (
+ `user_id` varchar(36) NOT NULL,
+ `seed_id` varchar(64) NOT NULL,
+ PRIMARY KEY (`user_id`,`seed_id`),
+ UNIQUE KEY `UK_dqxat2yuess97ol62itck0bul` (`user_id`),
+ UNIQUE KEY `UK_kf5p3eu6m26b6afhmmfcbdn8j` (`seed_id`),
+ KEY `fk_uf_seed` (`seed_id`),
+ CONSTRAINT `fk_uf_seed` FOREIGN KEY (`seed_id`) REFERENCES `Seed` (`seed_id`) ON DELETE CASCADE,
+ CONSTRAINT `fk_uf_user` FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `UserFavorite`
+--
+
+LOCK TABLES `UserFavorite` WRITE;
+/*!40000 ALTER TABLE `UserFavorite` DISABLE KEYS */;
+INSERT INTO `UserFavorite` VALUES ('550e8400-e29b-41d4-a716-446655440000','seed004'),('550e8400-e29b-41d4-a716-446655440003','seed009'),('550e8400-e29b-41d4-a716-446655440008','seed001');
+/*!40000 ALTER TABLE `UserFavorite` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `UserInvite`
+--
+
+DROP TABLE IF EXISTS `UserInvite`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `UserInvite` (
+ `user_id` varchar(36) NOT NULL,
+ `inviter_email` varchar(255) NOT NULL,
+ `inviter_registered` tinyint(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`user_id`,`inviter_email`),
+ CONSTRAINT `fk_ui_user` FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `UserInvite`
+--
+
+LOCK TABLES `UserInvite` WRITE;
+/*!40000 ALTER TABLE `UserInvite` DISABLE KEYS */;
+INSERT INTO `UserInvite` VALUES ('550e8400-e29b-41d4-a716-446655440000','user009@example.com',1),('550e8400-e29b-41d4-a716-446655440003','user002@example.com',1),('550e8400-e29b-41d4-a716-446655440008','user007@example.com',1);
+/*!40000 ALTER TABLE `UserInvite` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `UserMigration`
+--
+
+DROP TABLE IF EXISTS `UserMigration`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `UserMigration` (
+ `migration_id` varchar(64) NOT NULL,
+ `user_id` varchar(36) NOT NULL,
+ `application_url` varchar(255) NOT NULL,
+ `approved` tinyint(1) NOT NULL DEFAULT '0',
+ `pending_magic` int NOT NULL DEFAULT '0',
+ `granted_magic` int NOT NULL DEFAULT '0',
+ `pending_uploaded` bigint NOT NULL DEFAULT '0',
+ `granted_uploaded` bigint NOT NULL DEFAULT '0',
+ PRIMARY KEY (`migration_id`),
+ KEY `fk_um_user` (`user_id`),
+ CONSTRAINT `fk_um_user` FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `UserMigration`
+--
+
+LOCK TABLES `UserMigration` WRITE;
+/*!40000 ALTER TABLE `UserMigration` DISABLE KEYS */;
+/*!40000 ALTER TABLE `UserMigration` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `UserPT`
+--
+
+DROP TABLE IF EXISTS `UserPT`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `UserPT` (
+ `user_id` varchar(36) NOT NULL,
+ `magic` int NOT NULL DEFAULT '0',
+ `uploaded` bigint NOT NULL DEFAULT '0',
+ `downloaded` bigint NOT NULL DEFAULT '0',
+ `ratio` decimal(5,2) NOT NULL DEFAULT '0.00',
+ `default_seed_path` varchar(255) DEFAULT NULL,
+ `vip_downloads` int NOT NULL DEFAULT '0',
+ PRIMARY KEY (`user_id`),
+ CONSTRAINT `fk_pt_user` FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `UserPT`
+--
+
+LOCK TABLES `UserPT` WRITE;
+/*!40000 ALTER TABLE `UserPT` DISABLE KEYS */;
+INSERT INTO `UserPT` VALUES ('550e8400-e29b-41d4-a716-446655440000',0,0,0,0.00,'/data/seeds/550e8400-e29b-41d4-a716-446655440000',0),('550e8400-e29b-41d4-a716-446655440003',4096,4194304,2097152,2.00,'/data/seeds/550e8400-e29b-41d4-a716-446655440003',5),('550e8400-e29b-41d4-a716-446655440008',65536,65536000,32768000,2.00,'/data/seeds/550e8400-e29b-41d4-a716-446655440008',6);
+/*!40000 ALTER TABLE `UserPT` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `UserVotes`
+--
+
+DROP TABLE IF EXISTS `UserVotes`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `UserVotes` (
+ `user_id` varchar(36) NOT NULL,
+ `beg_id` varchar(64) NOT NULL,
+ `seed_id` varchar(64) NOT NULL,
+ `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`user_id`,`beg_id`,`seed_id`),
+ KEY `beg_id` (`beg_id`),
+ KEY `seed_id` (`seed_id`),
+ CONSTRAINT `UserVotes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`) ON DELETE CASCADE,
+ CONSTRAINT `UserVotes_ibfk_2` FOREIGN KEY (`beg_id`) REFERENCES `BegSeed` (`beg_id`) ON DELETE CASCADE,
+ CONSTRAINT `UserVotes_ibfk_3` FOREIGN KEY (`seed_id`) REFERENCES `Seed` (`seed_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `UserVotes`
+--
+
+LOCK TABLES `UserVotes` WRITE;
+/*!40000 ALTER TABLE `UserVotes` DISABLE KEYS */;
+INSERT INTO `UserVotes` VALUES ('550e8400-e29b-41d4-a716-446655440000','test_beg_settle_1749112257693','test_seed_settle_1749112257695','2025-06-05 08:30:58'),('550e8400-e29b-41d4-a716-446655440000','test_beg_settle_1749113033612','test_seed_settle_1749113033614','2025-06-05 08:43:54'),('550e8400-e29b-41d4-a716-446655440000','test_beg_settle_1749115170790','test_seed_settle_1749115170791','2025-06-05 09:19:31');
+/*!40000 ALTER TABLE `UserVotes` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `VipSeed`
+--
+
+DROP TABLE IF EXISTS `VipSeed`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!50503 SET character_set_client = utf8mb4 */;
+CREATE TABLE `VipSeed` (
+ `seed_id` varchar(64) NOT NULL,
+ `seeder_count` int NOT NULL DEFAULT '0',
+ `reward_magic` int NOT NULL DEFAULT '0',
+ `stop_caching` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0=继续缓存,1=不缓存',
+ `bonus` int NOT NULL,
+ `cache_status` bit(1) NOT NULL,
+ `farmer_number` int NOT NULL,
+ PRIMARY KEY (`seed_id`),
+ CONSTRAINT `fk_vip_seed` FOREIGN KEY (`seed_id`) REFERENCES `Seed` (`seed_id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `VipSeed`
+--
+
+LOCK TABLES `VipSeed` WRITE;
+/*!40000 ALTER TABLE `VipSeed` DISABLE KEYS */;
+INSERT INTO `VipSeed` VALUES ('seed001',5,50,0,10,_binary '',2),('seed004',8,80,0,15,_binary '',4),('seed009',30,300,0,60,_binary '\0',15);
+/*!40000 ALTER TABLE `VipSeed` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2025-06-05 9:45:32
diff --git a/trackerServer b/trackerServer
new file mode 160000
index 0000000..bbe2ea1
--- /dev/null
+++ b/trackerServer
@@ -0,0 +1 @@
+Subproject commit bbe2ea1f3844c884654fc7f70b641e983c9dfe10