torrust_index/services/
torrent_file.rs1use uuid::Uuid;
3
4use crate::models::torrent_file::{Torrent, TorrentFile, TorrentInfoDictionary};
5use crate::services::hasher::sha1;
6
7pub struct CreateTorrentRequest {
12 pub name: String,
14 pub pieces_or_root_hash: String,
15 pub piece_length: i64,
16 pub private: Option<u8>,
17 pub is_bep_30: i64,
19 pub files: Vec<TorrentFile>,
20 pub announce_urls: Vec<Vec<String>>,
22 pub comment: Option<String>,
23 pub creation_date: Option<i64>,
24 pub created_by: Option<String>,
25 pub encoding: Option<String>,
26}
27
28impl CreateTorrentRequest {
29 #[must_use]
35 pub fn build_torrent(&self) -> Torrent {
36 let info_dict = self.build_info_dictionary();
37
38 Torrent {
39 info: info_dict,
40 announce: None,
41 nodes: None,
42 encoding: self.encoding.clone(),
43 httpseeds: None,
44 announce_list: Some(self.announce_urls.clone()),
45 creation_date: self.creation_date,
46 comment: self.comment.clone(),
47 created_by: self.created_by.clone(),
48 }
49 }
50
51 #[must_use]
57 fn build_info_dictionary(&self) -> TorrentInfoDictionary {
58 TorrentInfoDictionary::with(
59 &self.name,
60 self.piece_length,
61 self.private,
62 self.is_bep_30,
63 &self.pieces_or_root_hash,
64 &self.files,
65 )
66 }
67}
68
69#[must_use]
78pub fn generate_random_torrent(id: Uuid) -> Torrent {
79 let file_contents = format!("{id}\n");
82
83 let torrent_files: Vec<TorrentFile> = vec![TorrentFile {
84 path: vec![String::new()],
85 length: i64::try_from(file_contents.len()).expect("file contents size in bytes cannot exceed i64::MAX"),
86 md5sum: None,
87 }];
88
89 let torrent_announce_urls: Vec<Vec<String>> = vec![];
90
91 let create_torrent_req = CreateTorrentRequest {
92 name: format!("file-{id}.txt"),
93 pieces_or_root_hash: sha1(&file_contents),
94 piece_length: 16384,
95 private: None,
96 is_bep_30: 0,
97 files: torrent_files,
98 announce_urls: torrent_announce_urls,
99 comment: None,
100 creation_date: None,
101 created_by: None,
102 encoding: None,
103 };
104
105 create_torrent_req.build_torrent()
106}
107
108#[cfg(test)]
109mod tests {
110 use serde_bytes::ByteBuf;
111 use uuid::Uuid;
112
113 use crate::models::torrent_file::{Torrent, TorrentInfoDictionary};
114 use crate::services::torrent_file::generate_random_torrent;
115
116 #[test]
117 fn it_should_generate_a_random_meta_info_file() {
118 let uuid = Uuid::parse_str("d6170378-2c14-4ccc-870d-2a8e15195e23").unwrap();
119
120 let torrent = generate_random_torrent(uuid);
121
122 let expected_torrent = Torrent {
123 info: TorrentInfoDictionary {
124 name: "file-d6170378-2c14-4ccc-870d-2a8e15195e23.txt".to_string(),
125 pieces: Some(ByteBuf::from(vec![
126 62, 231, 243, 51, 234, 165, 204, 209, 51, 132, 163, 133, 249, 50, 107, 46, 24, 15, 251, 32,
127 ])),
128 piece_length: 16384,
129 md5sum: None,
130 length: Some(37),
131 files: None,
132 private: None,
133 path: None,
134 root_hash: None,
135 source: None,
136 },
137 announce: None,
138 announce_list: Some(vec![]),
139 creation_date: None,
140 comment: None,
141 created_by: None,
142 nodes: None,
143 encoding: None,
144 httpseeds: None,
145 };
146
147 assert_eq!(torrent, expected_torrent);
148 }
149}