blob: 41d9052835a425f173e227b592546ab9638eb180 [file] [log] [blame]
Raverf79fdb62025-06-03 06:02:49 +00001package api;
2
3import java.io.File;
4
Raveraae06122025-06-05 08:13:35 +00005import javax.annotation.PostConstruct;
6
Raverf79fdb62025-06-03 06:02:49 +00007import org.springframework.core.io.FileSystemResource;
8import org.springframework.core.io.Resource;
9import org.springframework.http.HttpHeaders;
Raveraae06122025-06-05 08:13:35 +000010import org.springframework.http.HttpStatus;
Raverf79fdb62025-06-03 06:02:49 +000011import org.springframework.http.MediaType;
12import org.springframework.http.ResponseEntity;
13import org.springframework.web.bind.annotation.RequestParam;
14import org.springframework.web.bind.annotation.RestController;
15import org.springframework.web.multipart.MultipartFile;
Raveraae06122025-06-05 08:13:35 +000016import org.springframework.web.bind.annotation.CrossOrigin;
rhjc6a4ee02025-06-06 00:45:18 +080017import org.springframework.web.bind.annotation.RequestBody;
18import org.springframework.web.bind.annotation.PostMapping;
Raveraae06122025-06-05 08:13:35 +000019
20import com.fasterxml.jackson.core.JsonProcessingException;
21import com.fasterxml.jackson.databind.ObjectMapper;
Raverf79fdb62025-06-03 06:02:49 +000022
23import database.Database1;
Raverf79fdb62025-06-03 06:02:49 +000024import tracker.Tracker;
25
rhjc6a4ee02025-06-06 00:45:18 +080026import entity.Seed;
27import entity.User;
28
29import java.util.UUID;
Raveraae06122025-06-05 08:13:35 +000030
Raverf79fdb62025-06-03 06:02:49 +000031@RestController
32public class ApiController implements ApiInterface {
33
Raveraae06122025-06-05 08:13:35 +000034 private static Database1 db1;
Raverf79fdb62025-06-03 06:02:49 +000035 private static Tracker tracker;
Raveraae06122025-06-05 08:13:35 +000036 private static ObjectMapper mapper;
rhjc6a4ee02025-06-06 00:45:18 +080037 private static HttpHeaders headers;
38 private static HttpHeaders errorHeaders;
Raveraae06122025-06-05 08:13:35 +000039
40 @PostConstruct
41 public void init() {
42 db1 = new Database1();
43 tracker = new Tracker();
44 mapper = new ObjectMapper();
45 mapper.configure(com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
rhjc6a4ee02025-06-06 00:45:18 +080046 headers = new HttpHeaders();
47 headers.add("Access-Control-Allow-Origin", "*");
48 headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
49 headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization");
50 errorHeaders = new HttpHeaders();
51 errorHeaders.add("Access-Control-Allow-Origin", "*");
52 errorHeaders.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
53 errorHeaders.add("Access-Control-Allow-Headers", "Content-Type, Authorization");
Raveraae06122025-06-05 08:13:35 +000054 }
Raverf79fdb62025-06-03 06:02:49 +000055
56 @Override
57 public ResponseEntity<Integer> saveTorrent(
58 @RequestParam("userid") String userid,
59 @RequestParam("title") String title,
60 @RequestParam("tag") String tag,
61 @RequestParam("file") MultipartFile file
62 ) {
63 try {
64 Seed seed = new Seed();
rhjc6a4ee02025-06-06 00:45:18 +080065 seed.seedid = UUID.randomUUID().toString(); // 生成唯一的种子ID
66 seed.seeduserid = userid;
67 seed.title = title;
68 seed.seedsize = "1GB";
69 seed.seedtag = tag;
Raverf79fdb62025-06-03 06:02:49 +000070 seed.url = "http://example.com/torrent"; // 示例URL
rhjc6a4ee02025-06-06 00:45:18 +080071 System.out.println("seed is null? " + (seed == null));
Raveraae06122025-06-05 08:13:35 +000072 int ret = db1.RegisterSeed(seed);
rhjc6a4ee02025-06-06 00:45:18 +080073 if (ret != 0) {
74 // 如果注册种子失败,返回错误状态
75 return new ResponseEntity<>(ret, headers, HttpStatus.INTERNAL_SERVER_ERROR);
76 }
Raverf79fdb62025-06-03 06:02:49 +000077 File tempFile = File.createTempFile(seed.seedid, file.getOriginalFilename());
78 file.transferTo(tempFile);
79 tracker.SaveTorrent(seed.seedid, tempFile);
Raveraae06122025-06-05 08:13:35 +000080 return new ResponseEntity<>(0, headers, HttpStatus.OK); // 返回 0 表示成功
Raverf79fdb62025-06-03 06:02:49 +000081 } catch (Exception e) {
82 e.printStackTrace();
Raveraae06122025-06-05 08:13:35 +000083 return new ResponseEntity<>(1, errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR); // 返回 1 表示失败
Raverf79fdb62025-06-03 06:02:49 +000084 }
85 }
86
87 @Override
Raveraae06122025-06-05 08:13:35 +000088 @CrossOrigin(origins = "*", allowedHeaders = "*") // 允许所有来源和头部
Raverf79fdb62025-06-03 06:02:49 +000089 public ResponseEntity<Resource> getTorrent(
rhjc6a4ee02025-06-06 00:45:18 +080090 @RequestParam("torrentId") String seedid,
91 @RequestParam("userId") String userid
Raverf79fdb62025-06-03 06:02:49 +000092 ) {
Raveraae06122025-06-05 08:13:35 +000093 File file = tracker.GetTTorent(seedid, userid);
Raverf79fdb62025-06-03 06:02:49 +000094 if (file != null) {
95 FileSystemResource resource = new FileSystemResource(file);
96 return ResponseEntity.ok()
97 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"")
Raveraae06122025-06-05 08:13:35 +000098 .header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION) // 关键:允许前端访问Content-Disposition
Raverf79fdb62025-06-03 06:02:49 +000099 .contentType(MediaType.APPLICATION_OCTET_STREAM)
100 .body(resource);
101 } else {
Raveraae06122025-06-05 08:13:35 +0000102 return ResponseEntity.notFound().build();
103 }
104 }
105
Raveraae06122025-06-05 08:13:35 +0000106 @Override
107 public ResponseEntity<String> getSeedListByTag(
108 @RequestParam("tag") String tag
109 ) {
110 try {
111 Seed[] seeds = db1.GetSeedListByTag(tag);
rhjc6a4ee02025-06-06 00:45:18 +0800112 if (seeds == null || seeds.length == 0) {
113 return new ResponseEntity<>("[]", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR); // 返回 404 表示未找到种子
114 }
Raveraae06122025-06-05 08:13:35 +0000115 String json = mapper.writeValueAsString(seeds);
Raveraae06122025-06-05 08:13:35 +0000116 return new ResponseEntity<>(json, headers, HttpStatus.OK);
117 } catch (JsonProcessingException e) {
118 e.printStackTrace();
Raveraae06122025-06-05 08:13:35 +0000119 return new ResponseEntity<>("[]", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
120 }
121 }
122
123 @Override
rhjc6a4ee02025-06-06 00:45:18 +0800124 public ResponseEntity<String> getUserProfile(
125 @RequestParam("userid") String userid
126 ) {
127 try {
128 User user = db1.GetInformation(userid);
129 if (user == null) {
130 return new ResponseEntity<>("", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
131 }
132 String json = mapper.writeValueAsString(user);
133 return new ResponseEntity<>(json, headers, HttpStatus.OK);
134 } catch (JsonProcessingException e) {
135 e.printStackTrace();
136 return new ResponseEntity<>("", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
137 }
138 }
139
140 @Override
141 @CrossOrigin(origins = "*", allowedHeaders = "*")
142 public ResponseEntity<Integer> changeProfile(
143 @RequestBody String requestBody
144 ) {
145 try {
146 // 解析 JSON 数据
147 com.fasterxml.jackson.databind.JsonNode jsonNode = mapper.readTree(requestBody);
148
149 // 安全地获取 userid 字段
150 com.fasterxml.jackson.databind.JsonNode useridNode = jsonNode.get("userid");
151 if (useridNode == null) {
152 return new ResponseEntity<>(1, HttpStatus.BAD_REQUEST);
153 }
154 String userid = useridNode.asText();
155
156 // 添加参数验证
157 if (userid == null || userid.trim().isEmpty()) {
158 return new ResponseEntity<>(1, HttpStatus.BAD_REQUEST);
159 }
160
161 // 手动映射前端字段到 User 对象,处理类型转换
162 User user = new User();
163 user.userid = userid;
164
165 // 安全地获取其他字段并进行类型转换
166 if (jsonNode.has("username") && !jsonNode.get("username").isNull()) {
167 user.username = jsonNode.get("username").asText();
168 }
169 if (jsonNode.has("school") && !jsonNode.get("school").isNull()) {
170 user.school = jsonNode.get("school").asText();
171 }
172 if (jsonNode.has("gender") && !jsonNode.get("gender").isNull()) {
173 user.sex = jsonNode.get("gender").asText();
174 }
175 if (jsonNode.has("avatar_url") && !jsonNode.get("avatar_url").isNull()) {
176 user.pictureurl = jsonNode.get("avatar_url").asText();
177 }
178
179 // 处理 account_status 的类型转换(字符串/数字 -> 布尔值)
180 if (jsonNode.has("account_status") && !jsonNode.get("account_status").isNull()) {
181 com.fasterxml.jackson.databind.JsonNode statusNode = jsonNode.get("account_status");
182 if (statusNode.isTextual()) {
183 String statusStr = statusNode.asText();
184 user.accountstate = "1".equals(statusStr) || "封禁".equals(statusStr);
185 } else if (statusNode.isNumber()) {
186 user.accountstate = statusNode.asInt() == 1;
187 } else if (statusNode.isBoolean()) {
188 user.accountstate = statusNode.asBoolean();
189 }
190 }
191
192 // 处理 invite_left 的类型转换(字符串 -> 整数)
193 if (jsonNode.has("invite_left") && !jsonNode.get("invite_left").isNull()) {
194 com.fasterxml.jackson.databind.JsonNode inviteNode = jsonNode.get("invite_left");
195 if (inviteNode.isTextual()) {
196 try {
197 user.invitetimes = Integer.parseInt(inviteNode.asText());
198 } catch (NumberFormatException e) {
199 user.invitetimes = 0; // 默认值
200 }
201 } else if (inviteNode.isNumber()) {
202 user.invitetimes = inviteNode.asInt();
203 }
204 }
205
206 int ret = db1.UpdateInformation(user);
207 if (ret == 0) {
208 return new ResponseEntity<>(0, HttpStatus.OK); // 返回 0 表示成功
209 } else {
210 return new ResponseEntity<>(ret, HttpStatus.INTERNAL_SERVER_ERROR); // 返回其他状态表示失败
211 }
212 } catch (JsonProcessingException e) {
213 e.printStackTrace();
214 return new ResponseEntity<>(1, HttpStatus.INTERNAL_SERVER_ERROR); // 返回 1 表示处理失败
215 } catch (Exception e) {
216 e.printStackTrace();
217 return new ResponseEntity<>(1, HttpStatus.INTERNAL_SERVER_ERROR);
218 }
219 }
220
221 @Override
222 public ResponseEntity<String> getUserSeeds(
223 @RequestParam("userid") String userid
224 ) {
225 try {
226 Seed[] seeds = db1.GetSeedListByUser(userid);
227 if (seeds == null || seeds.length == 0) {
228 return new ResponseEntity<>("[]", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR); // 返回 404 表示未找到种子
229 }
230 String json = mapper.writeValueAsString(seeds);
231 return new ResponseEntity<>(json, headers, HttpStatus.OK);
232 } catch (JsonProcessingException e) {
233 e.printStackTrace();
234 return new ResponseEntity<>("[]", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
235 }
236 }
237
238 @Override
239 @CrossOrigin(origins = "*", allowedHeaders = "*")
240 public ResponseEntity<Integer> deleteSeed(
241 @RequestBody String requestBody
242 ) {
243 try {
244 // 解析 JSON 数据
245 com.fasterxml.jackson.databind.JsonNode jsonNode = mapper.readTree(requestBody);
246 com.fasterxml.jackson.databind.JsonNode seedidNode = jsonNode.get("seedid");
247 if (seedidNode == null) {
248 return new ResponseEntity<>(1, HttpStatus.BAD_REQUEST);
249 }
250 String seedid = seedidNode.asText();
251
252 // 添加参数验证
253 if (seedid == null || seedid.trim().isEmpty()) {
254 return new ResponseEntity<>(1, HttpStatus.BAD_REQUEST);
255 }
256
257 int ret = db1.DeleteSeed(seedid);
258 if (ret == 0) {
259 return new ResponseEntity<>(0, HttpStatus.OK);
260 } else {
261 return new ResponseEntity<>(ret, HttpStatus.INTERNAL_SERVER_ERROR);
262 }
263 } catch (Exception e) {
264 e.printStackTrace();
265 return new ResponseEntity<>(1, HttpStatus.INTERNAL_SERVER_ERROR);
266 }
267 }
268
269 @Override
270 public ResponseEntity<String> getUserStat(
271 @RequestParam("userid") String userid
272 ) {
273 try {
274 User user = db1.GetInformation(userid);
275 if (user == null) {
276 return new ResponseEntity<>("", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
277 }
278 String json = mapper.writeValueAsString(user);
279 return new ResponseEntity<>(json, headers, HttpStatus.OK);
280 } catch (JsonProcessingException e) {
281 e.printStackTrace();
282 return new ResponseEntity<>("", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
283 }
284 }
285
286 @Override
Raveraae06122025-06-05 08:13:35 +0000287 public ResponseEntity<String> getTorrentDetail(
288 @RequestParam("id") String seedid
289 ) {
290 try {
291 Seed seed = db1.GetSeedInformation(seedid);
292 if (seed != null) {
293 String json = mapper.writeValueAsString(seed);
294 HttpHeaders headers = new HttpHeaders();
295 headers.add("Access-Control-Allow-Origin", "*");
296 headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
297 headers.add("Access-Control-Allow-Headers", "Content-Type, Authorization");
298 return new ResponseEntity<>(json, headers, HttpStatus.OK);
299 } else {
300 return ResponseEntity.notFound().build(); // 返回 404 表示种子未找到
301 }
302 } catch (JsonProcessingException e) {
303 e.printStackTrace();
304 HttpHeaders errorHeaders = new HttpHeaders();
305 errorHeaders.add("Access-Control-Allow-Origin", "*");
306 errorHeaders.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
307 errorHeaders.add("Access-Control-Allow-Headers", "Content-Type, Authorization");
308 return new ResponseEntity<>("{}", errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
Raverf79fdb62025-06-03 06:02:49 +0000309 }
310 }
311}