blob: e405ef2975608229cc2a71c1831b12b1b5a36cb7 [file] [log] [blame]
22301102b1084372025-06-01 16:44:23 +08001package com.pt.controller;
2
3import com.pt.constant.Constants;
4import com.pt.entity.Resource;
5import com.pt.entity.User;
6import com.pt.service.ResourceService;
7import com.pt.service.UserService;
8import com.pt.utils.JWTUtils;
9import org.springframework.beans.factory.annotation.Autowired;
22301102f69709e2025-06-08 14:10:02 +080010import org.springframework.context.annotation.Bean;
22301102b1084372025-06-01 16:44:23 +080011import org.springframework.http.ResponseEntity;
12import org.springframework.web.bind.annotation.*;
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080013import org.springframework.web.multipart.MultipartFile;
22301102b1084372025-06-01 16:44:23 +080014
22301102bc6da0a2025-06-02 17:47:29 +080015import java.io.IOException;
22301102b1084372025-06-01 16:44:23 +080016import java.util.HashMap;
17import java.util.List;
18import java.util.Map;
22301102bc6da0a2025-06-02 17:47:29 +080019import java.io.File;
22301102b1084372025-06-01 16:44:23 +080020
21@RestController
22@RequestMapping("/api/resource")
23@CrossOrigin(origins = "*")
24public class ResourceController {
25
26 @Autowired
27 private ResourceService resourceService;
yyyangf786cfa2025-06-08 15:13:34 +080028
29 @Autowired
22301102b1084372025-06-01 16:44:23 +080030 private UserService userService;
31
32 @GetMapping("/list/all")
33 public ResponseEntity<?> getAllResources(@RequestHeader("token") String token,
34 @RequestParam("username") String username) {
22301102f69709e2025-06-08 14:10:02 +080035
22301102b1084372025-06-01 16:44:23 +080036 Map<String, Object> ans = new HashMap<>();
37
38 if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){
22301102f69709e2025-06-08 14:10:02 +080039 ans.put("message", "Invalid token");
22301102b1084372025-06-01 16:44:23 +080040 return ResponseEntity.badRequest().body(ans);
41 }
42
43 List<Resource> resources = resourceService.getAllResources();
44 if (resources.isEmpty()) {
45 return ResponseEntity.noContent().build();
46 }
22301102bc6da0a2025-06-02 17:47:29 +080047 return ResponseEntity.ok(resources);
22301102b1084372025-06-01 16:44:23 +080048 }
49
50 @GetMapping("/list/user")
51 public ResponseEntity<?> getUserResources(@RequestHeader("token") String token,
52 @RequestParam("username") String username) {
22301102f69709e2025-06-08 14:10:02 +080053
22301102b1084372025-06-01 16:44:23 +080054 Map<String, Object> ans = new HashMap<>();
55
56 if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){
22301102f69709e2025-06-08 14:10:02 +080057 ans.put("message", "Invalid token");
22301102b1084372025-06-01 16:44:23 +080058 return ResponseEntity.badRequest().body(ans);
59 }
60
61 List<Resource> resources = resourceService.getResourcesByAuthor(username);
62 if (resources.isEmpty()) {
63 return ResponseEntity.noContent().build();
64 }
65 return ResponseEntity.ok(resources);
66 }
67
68 @PostMapping("/publish")
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080069 public ResponseEntity<?> publishResource(
70 @RequestHeader("token") String token,
71 @RequestParam("username") String username,
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080072 @RequestParam("description") String description,
73 @RequestParam("torrent") MultipartFile torrentFile) {
74
22301102b1084372025-06-01 16:44:23 +080075 Map<String, Object> ans = new HashMap<>();
76
22301102bc6da0a2025-06-02 17:47:29 +080077 if (!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
22301102ca0fb2f2025-06-09 18:40:42 +080078 ans.put("result", "Invalid token");
22301102b1084372025-06-01 16:44:23 +080079 return ResponseEntity.badRequest().body(ans);
80 }
81
82 User user = userService.findByUsername(username);
22301102bc6da0a2025-06-02 17:47:29 +080083 if (user == null || user.getLevel() < 2) {
22301102ca0fb2f2025-06-09 18:40:42 +080084 ans.put("result", "Insufficient permissions to publish resources");
22301102b1084372025-06-01 16:44:23 +080085 return ResponseEntity.status(403).body(ans);
86 }
87
22301102bc6da0a2025-06-02 17:47:29 +080088 try {
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080089 // 传入种子文件字节,同时传入资源其他信息
Edwardsamaxlaf825a22025-06-09 21:17:29 +080090 System.out.println("name" + torrentFile.getOriginalFilename());
91 resourceService.publishResource(torrentFile.getOriginalFilename(), description, username, torrentFile.getSize(), torrentFile.getBytes());
22301102bc6da0a2025-06-02 17:47:29 +080092 } catch (Exception e) {
22301102ca0fb2f2025-06-09 18:40:42 +080093 ans.put("result", "Failed to publish resource: " + e.getMessage());
22301102bc6da0a2025-06-02 17:47:29 +080094 return ResponseEntity.status(500).body(ans);
95 }
22301102fe5f8412025-06-01 17:25:51 +080096
22301102ca0fb2f2025-06-09 18:40:42 +080097 ans.put("result", "Resource published successfully");
22301102b1084372025-06-01 16:44:23 +080098 return ResponseEntity.ok(ans);
99 }
100
22301102bc6da0a2025-06-02 17:47:29 +0800101
102
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +0800103
22301102b1084372025-06-01 16:44:23 +0800104 @GetMapping("/get/{resourceId}")
105 public ResponseEntity<?> getResourceById(@PathVariable("resourceId") int resourceId,
Edwardsamaxlaf825a22025-06-09 21:17:29 +0800106// @RequestHeader("token") String token,
22301102b1084372025-06-01 16:44:23 +0800107 @RequestParam("username") String username) {
108
109 Map<String, Object> ans = new HashMap<>();
Edwardsamaxlaf825a22025-06-09 21:17:29 +0800110// if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
111// ans.put("message", "Invalid token");
112// return ResponseEntity.badRequest().body(ans);
113// }
22301102b1084372025-06-01 16:44:23 +0800114
115 Resource resource = resourceService.getResourceById(resourceId);
116 if (resource == null) {
117 return ResponseEntity.notFound().build();
118 }
119 return ResponseEntity.ok(resource);
120 }
121
122 @GetMapping("/download/{resourceId}")
123 public ResponseEntity<?> downloadResource(@PathVariable("resourceId") int resourceId,
Edwardsamaxlaf825a22025-06-09 21:17:29 +0800124// @RequestHeader("token") String token,
22301102bc6da0a2025-06-02 17:47:29 +0800125 @RequestParam("username") String username) throws IOException {
22301102b1084372025-06-01 16:44:23 +0800126
127 Map<String, Object> ans = new HashMap<>();
Edwardsamaxlaf825a22025-06-09 21:17:29 +0800128// if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
129// ans.put("message", "Invalid token");
130// return ResponseEntity.badRequest().body(ans);
131// }
22301102b1084372025-06-01 16:44:23 +0800132
yyyangf786cfa2025-06-08 15:13:34 +0800133 User user = userService.findByUsername(username);
134 if (user == null) {
135 ans.put("message", "User not found");
136 return ResponseEntity.status(404).body(ans);
137 }
138
139 final double MIN_SHARE_RATIO_THRESHOLD = 0.5; // 最低共享率要求
140 final long DOWNLOAD_EXEMPTION_BYTES = 20L * 1024L * 1024L * 1024L; // 20GB下载量豁免
141
142 long uploaded = user.getUploaded();
143 long downloaded = user.getDownloaded();
144
145 // 如果用户的下载量超过豁免值,则检查其共享率
146 if (downloaded > DOWNLOAD_EXEMPTION_BYTES) {
147 // 防止除以零
148 double shareRatio = (downloaded == 0) ? Double.MAX_VALUE : (double) uploaded / downloaded;
149 if (shareRatio < MIN_SHARE_RATIO_THRESHOLD) {
150 ans.put("message", "Share ratio is too low. Please seed more to improve your ratio before downloading new resources.");
151 ans.put("current_share_ratio", String.format("%.2f", shareRatio));
152 ans.put("required_share_ratio", MIN_SHARE_RATIO_THRESHOLD);
153 return ResponseEntity.status(403).body(ans); // 403 Forbidden
154 }
155 }
156
22301102bc6da0a2025-06-02 17:47:29 +0800157 Resource resource = resourceService.getResourceById(resourceId);
158 byte[] file = resourceService.getTorrentFileByResource(resource, username);
159 if (file == null) {
160 return ResponseEntity.notFound().build();
161 }
22301102b1084372025-06-01 16:44:23 +0800162
22301102bc6da0a2025-06-02 17:47:29 +0800163 return ResponseEntity.ok()
164 .header("Content-Type", "application/x-bittorrent")
165 .header("Content-Disposition", "attachment; filename=\"" + resource.getName() + ".torrent\"")
166 .body(file);
22301102b1084372025-06-01 16:44:23 +0800167 }
168
169 @GetMapping("/search")
170 public ResponseEntity<?> searchResources(@RequestHeader("token") String token,
171 @RequestParam("username") String username,
172 @RequestParam("query") String query) {
173 Map<String, Object> ans = new HashMap<>();
174
175 if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){
22301102f69709e2025-06-08 14:10:02 +0800176 ans.put("message", "Invalid token");
22301102b1084372025-06-01 16:44:23 +0800177 return ResponseEntity.badRequest().body(ans);
178 }
179
180 List<Resource> resources = resourceService.searchByQuery(query);
181 if (resources.isEmpty()) {
182 return ResponseEntity.noContent().build();
183 }
184 return ResponseEntity.ok(resources);
185 }
186
187 @GetMapping("/delete")
188 public ResponseEntity<?> deleteResource(@RequestHeader("token") String token,
189 @RequestParam("username") String username,
190 @RequestParam("resourceId") int resourceId) {
191 Map<String, Object> ans = new HashMap<>();
192 Resource resource = resourceService.getResourceById(resourceId);
193
194 if(!JWTUtils.checkToken(token, username, Constants.UserRole.ADMIN) || resource == null || !resource.getAuthor().equals(username)) {
22301102f69709e2025-06-08 14:10:02 +0800195 ans.put("message", "Invalid token or insufficient permissions");
22301102b1084372025-06-01 16:44:23 +0800196 return ResponseEntity.badRequest().body(ans);
197 }
198
22301102bc6da0a2025-06-02 17:47:29 +0800199 try {
200 resourceService.deleteResource(resourceId);
201 } catch (Exception e) {
22301102f69709e2025-06-08 14:10:02 +0800202 ans.put("message", "Failed to delete resource: " + e.getMessage());
22301102bc6da0a2025-06-02 17:47:29 +0800203 return ResponseEntity.status(500).body(ans);
204 }
22301102b1084372025-06-01 16:44:23 +0800205
22301102f69709e2025-06-08 14:10:02 +0800206 ans.put("message", "Resource deleted successfully");
22301102b1084372025-06-01 16:44:23 +0800207 return ResponseEntity.ok(ans);
208 }
22301102bc6da0a2025-06-02 17:47:29 +0800209
22301102b1084372025-06-01 16:44:23 +0800210}