| package com.pt.controller; |
| |
| import com.pt.constant.Constants; |
| import com.pt.entity.Resource; |
| import com.pt.entity.User; |
| import com.pt.service.ResourceService; |
| import com.pt.service.UserService; |
| import com.pt.utils.JWTUtils; |
| import org.springframework.beans.factory.annotation.Autowired; |
| import org.springframework.context.annotation.Bean; |
| import org.springframework.http.ResponseEntity; |
| import org.springframework.web.bind.annotation.*; |
| import org.springframework.web.multipart.MultipartFile; |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.io.File; |
| |
| @RestController |
| @RequestMapping("/api/resource") |
| @CrossOrigin(origins = "*") |
| public class ResourceController { |
| |
| @Autowired |
| private ResourceService resourceService; |
| |
| @Autowired |
| private UserService userService; |
| |
| @GetMapping("/list/all") |
| public ResponseEntity<?> getAllResources(@RequestHeader("token") String token, |
| @RequestParam("username") String username) { |
| |
| Map<String, Object> ans = new HashMap<>(); |
| |
| if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){ |
| ans.put("message", "Invalid token"); |
| return ResponseEntity.badRequest().body(ans); |
| } |
| |
| List<Resource> resources = resourceService.getAllResources(); |
| if (resources.isEmpty()) { |
| return ResponseEntity.noContent().build(); |
| } |
| return ResponseEntity.ok(resources); |
| } |
| |
| @GetMapping("/list/user") |
| public ResponseEntity<?> getUserResources(@RequestHeader("token") String token, |
| @RequestParam("username") String username) { |
| |
| Map<String, Object> ans = new HashMap<>(); |
| |
| if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){ |
| ans.put("message", "Invalid token"); |
| return ResponseEntity.badRequest().body(ans); |
| } |
| |
| List<Resource> resources = resourceService.getResourcesByAuthor(username); |
| if (resources.isEmpty()) { |
| return ResponseEntity.noContent().build(); |
| } |
| return ResponseEntity.ok(resources); |
| } |
| |
| @PostMapping("/publish") |
| public ResponseEntity<?> publishResource( |
| @RequestHeader("token") String token, |
| @RequestParam("username") String username, |
| @RequestParam("size") double size, |
| @RequestParam("name") String name, |
| @RequestParam("description") String description, |
| @RequestParam("torrent") MultipartFile torrentFile) { |
| |
| Map<String, Object> ans = new HashMap<>(); |
| |
| if (!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) { |
| ans.put("message", "Invalid token"); |
| return ResponseEntity.badRequest().body(ans); |
| } |
| |
| User user = userService.findByUsername(username); |
| if (user == null || user.getLevel() < 2) { |
| ans.put("message", "Insufficient permissions to publish resources"); |
| return ResponseEntity.status(403).body(ans); |
| } |
| |
| try { |
| // 传入种子文件字节,同时传入资源其他信息 |
| resourceService.publishResource(name, description, username, size, torrentFile.getBytes()); |
| } catch (Exception e) { |
| ans.put("message", "Failed to publish resource: " + e.getMessage()); |
| return ResponseEntity.status(500).body(ans); |
| } |
| |
| ans.put("message", "Resource published successfully"); |
| return ResponseEntity.ok(ans); |
| } |
| |
| |
| |
| |
| @GetMapping("/get/{resourceId}") |
| public ResponseEntity<?> getResourceById(@PathVariable("resourceId") int resourceId, |
| @RequestHeader("token") String token, |
| @RequestParam("username") String username) { |
| |
| Map<String, Object> ans = new HashMap<>(); |
| if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) { |
| ans.put("message", "Invalid token"); |
| return ResponseEntity.badRequest().body(ans); |
| } |
| |
| Resource resource = resourceService.getResourceById(resourceId); |
| if (resource == null) { |
| return ResponseEntity.notFound().build(); |
| } |
| return ResponseEntity.ok(resource); |
| } |
| |
| @GetMapping("/download/{resourceId}") |
| public ResponseEntity<?> downloadResource(@PathVariable("resourceId") int resourceId, |
| @RequestHeader("token") String token, |
| @RequestParam("username") String username) throws IOException { |
| |
| Map<String, Object> ans = new HashMap<>(); |
| if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) { |
| ans.put("message", "Invalid token"); |
| return ResponseEntity.badRequest().body(ans); |
| } |
| |
| User user = userService.findByUsername(username); |
| if (user == null) { |
| ans.put("message", "User not found"); |
| return ResponseEntity.status(404).body(ans); |
| } |
| |
| final double MIN_SHARE_RATIO_THRESHOLD = 0.5; // 最低共享率要求 |
| final long DOWNLOAD_EXEMPTION_BYTES = 20L * 1024L * 1024L * 1024L; // 20GB下载量豁免 |
| |
| long uploaded = user.getUploaded(); |
| long downloaded = user.getDownloaded(); |
| |
| // 如果用户的下载量超过豁免值,则检查其共享率 |
| if (downloaded > DOWNLOAD_EXEMPTION_BYTES) { |
| // 防止除以零 |
| double shareRatio = (downloaded == 0) ? Double.MAX_VALUE : (double) uploaded / downloaded; |
| if (shareRatio < MIN_SHARE_RATIO_THRESHOLD) { |
| ans.put("message", "Share ratio is too low. Please seed more to improve your ratio before downloading new resources."); |
| ans.put("current_share_ratio", String.format("%.2f", shareRatio)); |
| ans.put("required_share_ratio", MIN_SHARE_RATIO_THRESHOLD); |
| return ResponseEntity.status(403).body(ans); // 403 Forbidden |
| } |
| } |
| |
| Resource resource = resourceService.getResourceById(resourceId); |
| byte[] file = resourceService.getTorrentFileByResource(resource, username); |
| if (file == null) { |
| return ResponseEntity.notFound().build(); |
| } |
| |
| return ResponseEntity.ok() |
| .header("Content-Type", "application/x-bittorrent") |
| .header("Content-Disposition", "attachment; filename=\"" + resource.getName() + ".torrent\"") |
| .body(file); |
| } |
| |
| @GetMapping("/search") |
| public ResponseEntity<?> searchResources(@RequestHeader("token") String token, |
| @RequestParam("username") String username, |
| @RequestParam("query") String query) { |
| Map<String, Object> ans = new HashMap<>(); |
| |
| if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){ |
| ans.put("message", "Invalid token"); |
| return ResponseEntity.badRequest().body(ans); |
| } |
| |
| List<Resource> resources = resourceService.searchByQuery(query); |
| if (resources.isEmpty()) { |
| return ResponseEntity.noContent().build(); |
| } |
| return ResponseEntity.ok(resources); |
| } |
| |
| @GetMapping("/delete") |
| public ResponseEntity<?> deleteResource(@RequestHeader("token") String token, |
| @RequestParam("username") String username, |
| @RequestParam("resourceId") int resourceId) { |
| Map<String, Object> ans = new HashMap<>(); |
| Resource resource = resourceService.getResourceById(resourceId); |
| |
| if(!JWTUtils.checkToken(token, username, Constants.UserRole.ADMIN) || resource == null || !resource.getAuthor().equals(username)) { |
| ans.put("message", "Invalid token or insufficient permissions"); |
| return ResponseEntity.badRequest().body(ans); |
| } |
| |
| try { |
| resourceService.deleteResource(resourceId); |
| } catch (Exception e) { |
| ans.put("message", "Failed to delete resource: " + e.getMessage()); |
| return ResponseEntity.status(500).body(ans); |
| } |
| |
| ans.put("message", "Resource deleted successfully"); |
| return ResponseEntity.ok(ans); |
| } |
| |
| } |