blob: e61e874c65ceccede8a61f151f2a1d93ce5cbc14 [file] [log] [blame]
22301102bc6da0a2025-06-02 17:47:29 +08001package com.pt.service;
2
3import com.pt.entity.TorrentMeta;
4import com.pt.repository.TorrentMetaRepository;
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +08005import com.pt.utils.BencodeCodec;
22301102bc6da0a2025-06-02 17:47:29 +08006import org.springframework.beans.factory.annotation.Autowired;
7import org.springframework.stereotype.Service;
8
22301102bc6da0a2025-06-02 17:47:29 +08009import java.security.MessageDigest;
10import java.time.LocalDateTime;
Edwardsamaxlcba512d2025-06-09 21:17:29 +080011import java.util.HashMap;
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080012import java.util.List;
22301102bc6da0a2025-06-02 17:47:29 +080013import java.util.Map;
22301102ca0fb2f2025-06-09 18:40:42 +080014import java.util.Optional;
22301102bc6da0a2025-06-02 17:47:29 +080015
16@Service
17public class TorrentService {
18
22301102bc6da0a2025-06-02 17:47:29 +080019 @Autowired
20 private TorrentMetaRepository torrentMetaRepository;
21
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080022 public TorrentMeta parseAndSaveTorrent(byte[] torrentBytes) throws Exception {
23 Map<String, Object> torrentDict = (Map<String, Object>) BencodeCodec.decode(torrentBytes);
24 if (!torrentDict.containsKey("info")) {
25 throw new IllegalArgumentException("Invalid torrent file: missing 'info' dictionary");
22301102bc6da0a2025-06-02 17:47:29 +080026 }
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080027
28 Map<String, Object> infoDict = (Map<String, Object>) torrentDict.get("info");
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080029 // 计算 info_hash
30 byte[] infoEncoded = BencodeCodec.encode(infoDict);
31 MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
32 byte[] infoHashBytes = sha1.digest(infoEncoded);
33 String infoHash = bytesToHex(infoHashBytes);
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080034 // 获取文件名,大小等
35 String name = (String) infoDict.get("name");
36 long length = 0;
37 if (infoDict.containsKey("length")) {
38 length = ((Number) infoDict.get("length")).longValue();
39 } else if (infoDict.containsKey("files")) {
40 long totalLength = 0;
41 List<Map<String, Object>> files = (List<Map<String, Object>>) infoDict.get("files");
42 for (Map<String, Object> file : files) {
43 totalLength += ((Number) file.get("length")).longValue();
44 }
45 length = totalLength;
46 }
Edwardsamaxlcba512d2025-06-09 21:17:29 +080047 // 添加Tracker地址到种子文件中
48 torrentDict.put("announce", "http://your-tracker-url/api/tracker/announce");
49
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080050 // 保存到数据库
22301102ca0fb2f2025-06-09 18:40:42 +080051 Optional<TorrentMeta> existing = torrentMetaRepository.findByInfoHash(infoHash);
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080052
22301102ca0fb2f2025-06-09 18:40:42 +080053 if (existing.isPresent()) {
54 System.out.println("该种子已存在,跳过保存");
55 return existing.get();
56 } else {
57 TorrentMeta meta = new TorrentMeta();
58 meta.setFilename(name);
59 meta.setInfoHash(infoHash);
60 meta.setSize(length);
61 meta.setUploadTime(LocalDateTime.now());
Edwardsamaxlcba512d2025-06-09 21:17:29 +080062 meta.setTorrentData(BencodeCodec.encode(torrentDict)); // 使用更新后的字典编码
22301102ca0fb2f2025-06-09 18:40:42 +080063
64 return torrentMetaRepository.save(meta);
65 }
66
22301102bc6da0a2025-06-02 17:47:29 +080067 }
68
Edwardsamaxlf1bf7ad2025-06-03 23:52:16 +080069
22301102bc6da0a2025-06-02 17:47:29 +080070 private String bytesToHex(byte[] bytes) {
71 StringBuilder sb = new StringBuilder();
72 for (byte b : bytes) {
73 sb.append(String.format("%02x", b));
74 }
75 return sb.toString();
76 }
Edwardsamaxlcba512d2025-06-09 21:17:29 +080077}