Skip to content

Commit 929b8a6

Browse files
author
yggverse
committed
export filename from torrent info, if exists
1 parent 3c31d48 commit 929b8a6

1 file changed

Lines changed: 43 additions & 8 deletions

File tree

crates/http/src/main.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ use config::Config;
1414
use feed::Feed;
1515
use info_hash::InfoHash;
1616
use meta::Meta;
17-
use rocket::{State, http::Status, response::content::RawXml, serde::Serialize};
17+
use rocket::{
18+
State,
19+
http::{ContentType, Header, Status},
20+
response::{Responder, Response, content::RawXml},
21+
serde::Serialize,
22+
};
1823
use rocket_dyn_templates::{Template, context};
1924
use torrent::Torrent;
2025

@@ -182,9 +187,6 @@ fn info(
182187
}
183188
}
184189

185-
#[derive(Responder)]
186-
#[response(status = 200, content_type = "application/x-bittorrent")]
187-
pub struct TorrentFile(Vec<u8>);
188190
/// Return .torrent file with updated trackers @TODO resolve rank collision
189191
#[get("/<filename>", rank = 2)]
190192
fn torrent_file(
@@ -235,10 +237,25 @@ fn torrent_file(
235237
.to_vec(),
236238
),
237239
);
238-
Ok(TorrentFile(serde_bencode::to_bytes(&b).map_err(|e| {
239-
error!("Could not encode torrent bytes: `{e}`");
240-
Status::InternalServerError
241-
})?))
240+
Ok(TorrentFile {
241+
name: format!(
242+
"{}.torrent",
243+
if let Some(Value::Dict(info)) = b.get("info") {
244+
if let Some(Value::Bytes(name_bytes)) = info.get(b"name".as_slice()) {
245+
String::from_utf8(name_bytes.clone())
246+
.unwrap_or(filename.id20().as_string())
247+
} else {
248+
filename.id20().as_string()
249+
}
250+
} else {
251+
filename.id20().as_string()
252+
}
253+
),
254+
data: serde_bencode::to_bytes(&b).map_err(|e| {
255+
error!("Could not encode torrent bytes: `{e}`");
256+
Status::InternalServerError
257+
})?,
258+
})
242259
}
243260
None => Err(Status::NotFound),
244261
}
@@ -342,3 +359,21 @@ fn rocket() -> _ {
342359
}
343360

344361
const S: &str = " • ";
362+
363+
/// Downloadable .torrent bytes, with meta-info updated
364+
struct TorrentFile {
365+
name: String,
366+
data: Vec<u8>,
367+
}
368+
impl<'r> Responder<'r, 'static> for TorrentFile {
369+
fn respond_to(self, _: &'r rocket::request::Request<'_>) -> rocket::response::Result<'static> {
370+
Response::build()
371+
.header(ContentType::new("application", "x-bittorrent"))
372+
.header(Header::new(
373+
"Content-Disposition",
374+
format!("attachment; filename=\"{}\"", self.name),
375+
))
376+
.sized_body(self.data.len(), std::io::Cursor::new(self.data))
377+
.ok()
378+
}
379+
}

0 commit comments

Comments
 (0)