mirror of
https://github.com/YGGverse/btracker.git
synced 2026-03-31 17:15:31 +00:00
implement magnet links
This commit is contained in:
parent
ec6d9a4e00
commit
7da285ca69
5 changed files with 58 additions and 31 deletions
24
src/feed.rs
24
src/feed.rs
|
|
@ -7,8 +7,7 @@ pub struct Feed {
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
link: Option<String>,
|
link: Option<String>,
|
||||||
title: String,
|
title: String,
|
||||||
/// Valid, parsed from Url, ready-to-use address string donor
|
trackers: Option<HashSet<Url>>,
|
||||||
trackers: Option<HashSet<String>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Feed {
|
impl Feed {
|
||||||
|
|
@ -22,7 +21,7 @@ impl Feed {
|
||||||
description: description.map(escape),
|
description: description.map(escape),
|
||||||
link: link.map(|s| escape(s.to_string())),
|
link: link.map(|s| escape(s.to_string())),
|
||||||
title: escape(title),
|
title: escape(title),
|
||||||
trackers: trackers.map(|v| v.into_iter().map(|u| u.to_string()).collect()),
|
trackers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,7 +69,7 @@ impl Feed {
|
||||||
.map(|b| b.to_string())
|
.map(|b| b.to_string())
|
||||||
.unwrap_or("?".into()) // @TODO
|
.unwrap_or("?".into()) // @TODO
|
||||||
),
|
),
|
||||||
escape(self.magnet(&torrent.info_hash))
|
escape(format::magnet(&torrent.info_hash, self.trackers.as_ref()))
|
||||||
));
|
));
|
||||||
|
|
||||||
if let Some(d) = item_description(torrent.length, torrent.files) {
|
if let Some(d) = item_description(torrent.length, torrent.files) {
|
||||||
|
|
@ -91,23 +90,6 @@ impl Feed {
|
||||||
buffer.push_str("</channel></rss>");
|
buffer.push_str("</channel></rss>");
|
||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tools
|
|
||||||
|
|
||||||
fn magnet(&self, info_hash: &str) -> String {
|
|
||||||
let mut b = if info_hash.len() == 40 {
|
|
||||||
format!("magnet:?xt=urn:btih:{info_hash}")
|
|
||||||
} else {
|
|
||||||
todo!("info-hash v2 is not supported by librqbit")
|
|
||||||
};
|
|
||||||
if let Some(ref trackers) = self.trackers {
|
|
||||||
for tracker in trackers {
|
|
||||||
b.push_str("&tr=");
|
|
||||||
b.push_str(&urlencoding::encode(tracker))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn escape(subject: String) -> String {
|
fn escape(subject: String) -> String {
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,18 @@ pub fn bytes(value: u64) -> String {
|
||||||
format!("{:.2} GB", f / GB)
|
format!("{:.2} GB", f / GB)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn magnet(info_hash: &str, trackers: Option<&std::collections::HashSet<url::Url>>) -> String {
|
||||||
|
let mut b = if info_hash.len() == 40 {
|
||||||
|
format!("magnet:?xt=urn:btih:{info_hash}")
|
||||||
|
} else {
|
||||||
|
todo!("info-hash v2 is not supported by librqbit")
|
||||||
|
};
|
||||||
|
if let Some(t) = trackers {
|
||||||
|
for tracker in t {
|
||||||
|
b.push_str("&tr=");
|
||||||
|
b.push_str(&urlencoding::encode(tracker.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b
|
||||||
|
}
|
||||||
|
|
|
||||||
23
src/main.rs
23
src/main.rs
|
|
@ -15,7 +15,8 @@ use rocket::{
|
||||||
serde::Serialize,
|
serde::Serialize,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{Template, context};
|
use rocket_dyn_templates::{Template, context};
|
||||||
use storage::{Order, Sort, Storage};
|
use std::collections::HashSet;
|
||||||
|
use storage::{Order, Sort, Storage, Torrent};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
|
@ -25,21 +26,33 @@ pub struct Meta {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub stats: Option<Url>,
|
pub stats: Option<Url>,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub trackers: Option<Vec<Url>>,
|
pub trackers: Option<HashSet<Url>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
fn index(storage: &State<Storage>, meta: &State<Meta>) -> Result<Template, Custom<String>> {
|
fn index(storage: &State<Storage>, meta: &State<Meta>) -> Result<Template, Custom<String>> {
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
struct Row {
|
||||||
|
torrent: Torrent,
|
||||||
|
magnet: String,
|
||||||
|
}
|
||||||
Ok(Template::render(
|
Ok(Template::render(
|
||||||
"index",
|
"index",
|
||||||
context! {
|
context! {
|
||||||
meta: meta.inner(),
|
meta: meta.inner(),
|
||||||
torrents: storage
|
rows: storage
|
||||||
.torrents(
|
.torrents(
|
||||||
Some((Sort::Modified, Order::Asc)),
|
Some((Sort::Modified, Order::Asc)),
|
||||||
Some(storage.default_limit),
|
Some(storage.default_limit),
|
||||||
)
|
)
|
||||||
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))?
|
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))?
|
||||||
|
.into_iter()
|
||||||
|
.map(|torrent| Row {
|
||||||
|
magnet: format::magnet(&torrent.info_hash, meta.trackers.as_ref()),
|
||||||
|
torrent,
|
||||||
|
})
|
||||||
|
.collect::<Vec<Row>>()
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +80,7 @@ fn rocket() -> _ {
|
||||||
config.title.clone(),
|
config.title.clone(),
|
||||||
config.description.clone(),
|
config.description.clone(),
|
||||||
config.link.clone(),
|
config.link.clone(),
|
||||||
config.tracker.clone().map(|u| u.into_iter().collect()), // make sure it's unique
|
config.tracker.clone().map(|u| u.into_iter().collect()),
|
||||||
);
|
);
|
||||||
let storage = Storage::init(config.storage, config.limit, config.capacity).unwrap(); // @TODO handle
|
let storage = Storage::init(config.storage, config.limit, config.capacity).unwrap(); // @TODO handle
|
||||||
rocket::build()
|
rocket::build()
|
||||||
|
|
@ -84,7 +97,7 @@ fn rocket() -> _ {
|
||||||
description: config.description,
|
description: config.description,
|
||||||
stats: config.stats,
|
stats: config.stats,
|
||||||
title: config.title,
|
title: config.title,
|
||||||
trackers: config.tracker,
|
trackers: config.tracker.map(|u| u.into_iter().collect()),
|
||||||
})
|
})
|
||||||
.mount("/", routes![index, rss])
|
.mount("/", routes![index, rss])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
{% extends "layout/default" %}
|
{% extends "layout/default" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% for torrent in torrents %}
|
{% for row in rows %}
|
||||||
<div>
|
<div>
|
||||||
<a name="{{ torrent.info_hash }}"></a>
|
<a name="{{ row.torrent.info_hash }}"></a>
|
||||||
<h2>{{ torrent.name }}</h2>
|
<h2>{{ row.torrent.name }}</h2>
|
||||||
</div>
|
<div>
|
||||||
|
<a rel="nofollow" href="{{ row.magnet }}" title="Magnet">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M15 12h-4v3h4v-3ZM5 12H1v3h4v-3ZM0 8a8 8 0 1 1 16 0v8h-6V8a2 2 0 1 0-4 0v8H0V8Z"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
@ -86,12 +86,22 @@
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* item row */
|
||||||
main > div {
|
main > div {
|
||||||
background-color: #34384f;
|
background-color: #34384f;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* controls */
|
||||||
|
main > div > div {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
main > div > div > a> svg {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue