reddit-magnet/src/magnet.rs
Marc Plano-Lesay 70684eb2a2
Use a structured magnet URL type
This will be required to parse them and submit them to bitmagnet.
2025-05-01 20:25:55 +10:00

127 lines
3.4 KiB
Rust

use color_eyre::eyre::{eyre, Result};
use magnet_url::Magnet;
/// Extract magnet links from text
pub fn extract_magnet_links(text: &str) -> Result<Vec<Magnet>> {
let mut links = Vec::new();
let mut start_idx = 0;
while let Some(idx) = text[start_idx..].find("magnet:") {
let start = start_idx + idx;
let end = text[start..]
.find(char::is_whitespace)
.map(|e| start + e)
.unwrap_or(text.len());
let link = &text[start..end];
let magnet = Magnet::new(link)
.map_err(|e| eyre!("Failed to parse magnet link '{}': {:?}", link, e))?;
links.push(magnet);
start_idx = end;
}
Ok(links)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_text() {
let text = "";
let links = extract_magnet_links(text);
assert!(links.unwrap().is_empty());
}
#[test]
fn test_no_magnet_links() {
let text = "This is a text without any magnet links";
let links = extract_magnet_links(text);
assert!(links.unwrap().is_empty());
}
#[test]
fn test_single_magnet_link() {
let text = "Here is a magnet link: magnet:?xt=urn:btih:example";
let links = extract_magnet_links(text).unwrap();
assert_eq!(links.len(), 1);
assert_eq!(
links[0],
Magnet::new_no_validation("magnet:?xt=urn:btih:example")
);
}
#[test]
fn test_multiple_magnet_links() {
let text = "First link: magnet:?xt=urn:btih:example1 and second link: magnet:?xt=urn:btih:example2";
let links = extract_magnet_links(text).unwrap();
assert_eq!(links.len(), 2);
assert_eq!(
links[0],
Magnet::new_no_validation("magnet:?xt=urn:btih:example1")
);
assert_eq!(
links[1],
Magnet::new_no_validation("magnet:?xt=urn:btih:example2")
);
}
#[test]
fn test_magnet_link_at_beginning() {
let text = "magnet:?xt=urn:btih:example at the beginning";
let links = extract_magnet_links(text).unwrap();
assert_eq!(links.len(), 1);
assert_eq!(
links[0],
Magnet::new_no_validation("magnet:?xt=urn:btih:example")
);
}
#[test]
fn test_magnet_link_at_end() {
let text = "Link at the end: magnet:?xt=urn:btih:example";
let links = extract_magnet_links(text).unwrap();
assert_eq!(links.len(), 1);
assert_eq!(
links[0],
Magnet::new_no_validation("magnet:?xt=urn:btih:example")
);
}
#[test]
fn test_magnet_link_without_whitespace() {
let text = "Text containing a link:magnet:?xt=urn:btih:example";
let links = extract_magnet_links(text).unwrap();
assert_eq!(links.len(), 1);
assert_eq!(
links[0],
Magnet::new_no_validation("magnet:?xt=urn:btih:example")
);
}
#[test]
fn test_complex_magnet_link() {
let text = "Complex link: magnet:?xt=urn:btih:a1b2c3d4e5f6g7h8i9j0&dn=example+file&tr=udp%3A%2F%2Ftracker.example.com%3A80";
let links = extract_magnet_links(text).unwrap();
assert_eq!(links.len(), 1);
assert_eq!(links[0], Magnet::new_no_validation("magnet:?xt=urn:btih:a1b2c3d4e5f6g7h8i9j0&dn=example+file&tr=udp%3A%2F%2Ftracker.example.com%3A80"));
}
}