Reject duplicate links
This commit is contained in:
parent
b157985bf3
commit
4de127f2d2
3 changed files with 78 additions and 0 deletions
1
migrations/2025-04-30-120032_unique_magnet/down.sql
Normal file
1
migrations/2025-04-30-120032_unique_magnet/down.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DROP INDEX magnets_unique_link;
|
||||||
1
migrations/2025-04-30-120032_unique_magnet/up.sql
Normal file
1
migrations/2025-04-30-120032_unique_magnet/up.sql
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
CREATE UNIQUE INDEX magnets_unique_link ON magnets(link);
|
||||||
76
src/db.rs
76
src/db.rs
|
|
@ -69,6 +69,73 @@ mod tests {
|
||||||
assert_eq!(magnet.published_at, expected_timestamp);
|
assert_eq!(magnet.published_at, expected_timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_prevent_duplicate_magnets() {
|
||||||
|
let temp_dir = tempdir().unwrap();
|
||||||
|
let db_path = temp_dir.path().join("test.db");
|
||||||
|
|
||||||
|
let mut db = Database::new(&db_path).unwrap();
|
||||||
|
|
||||||
|
// Create initial post with magnet links
|
||||||
|
let post_info = PostInfo {
|
||||||
|
title: "Test Title".to_string(),
|
||||||
|
submitter: "test_user".to_string(),
|
||||||
|
subreddit: "test_subreddit".to_string(),
|
||||||
|
magnet_links: vec![
|
||||||
|
"magnet:?xt=urn:btih:test1".to_string(),
|
||||||
|
"magnet:?xt=urn:btih:test2".to_string(),
|
||||||
|
],
|
||||||
|
timestamp: Utc::now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// First insertion should succeed and insert 2 links
|
||||||
|
let result = db.store_magnets(&post_info);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
assert_eq!(result.unwrap(), 2); // 2 links inserted
|
||||||
|
|
||||||
|
// Create a second post with some duplicate and some new links
|
||||||
|
let post_info2 = PostInfo {
|
||||||
|
title: "Test Title 2".to_string(),
|
||||||
|
submitter: "test_user2".to_string(),
|
||||||
|
subreddit: "test_subreddit2".to_string(),
|
||||||
|
magnet_links: vec![
|
||||||
|
"magnet:?xt=urn:btih:test1".to_string(), // Duplicate
|
||||||
|
"magnet:?xt=urn:btih:test3".to_string(), // New
|
||||||
|
],
|
||||||
|
timestamp: Utc::now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Second insertion should succeed but only insert the new link
|
||||||
|
let result2 = db.store_magnets(&post_info2);
|
||||||
|
assert!(result2.is_ok());
|
||||||
|
assert_eq!(result2.unwrap(), 1); // Only 1 new link inserted
|
||||||
|
|
||||||
|
// Verify we have 3 total links in the database
|
||||||
|
let magnets = db.get_all_magnets().unwrap();
|
||||||
|
assert_eq!(magnets.len(), 3);
|
||||||
|
|
||||||
|
// Try inserting only duplicates
|
||||||
|
let post_info3 = PostInfo {
|
||||||
|
title: "Test Title 3".to_string(),
|
||||||
|
submitter: "test_user3".to_string(),
|
||||||
|
subreddit: "test_subreddit3".to_string(),
|
||||||
|
magnet_links: vec![
|
||||||
|
"magnet:?xt=urn:btih:test1".to_string(), // Duplicate
|
||||||
|
"magnet:?xt=urn:btih:test2".to_string(), // Duplicate
|
||||||
|
],
|
||||||
|
timestamp: Utc::now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Third insertion should succeed but insert 0 links
|
||||||
|
let result3 = db.store_magnets(&post_info3);
|
||||||
|
assert!(result3.is_ok());
|
||||||
|
assert_eq!(result3.unwrap(), 0); // No new links inserted
|
||||||
|
|
||||||
|
// Verify we still have 3 total links in the database
|
||||||
|
let magnets = db.get_all_magnets().unwrap();
|
||||||
|
assert_eq!(magnets.len(), 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
|
|
@ -103,9 +170,18 @@ impl Database {
|
||||||
|
|
||||||
pub fn store_magnets(&mut self, post: &PostInfo) -> Result<usize> {
|
pub fn store_magnets(&mut self, post: &PostInfo) -> Result<usize> {
|
||||||
let published_at = post.timestamp.naive_utc();
|
let published_at = post.timestamp.naive_utc();
|
||||||
|
|
||||||
|
// Filter out magnet links that already exist in the database
|
||||||
|
let existing_links: Vec<String> = magnets::table
|
||||||
|
.select(magnets::link)
|
||||||
|
.filter(magnets::link.eq_any(&post.magnet_links))
|
||||||
|
.load(&mut self.conn)
|
||||||
|
.wrap_err("Failed to query existing magnets")?;
|
||||||
|
|
||||||
let links = post
|
let links = post
|
||||||
.magnet_links
|
.magnet_links
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|link| !existing_links.contains(link))
|
||||||
.map(|m| NewMagnet {
|
.map(|m| NewMagnet {
|
||||||
title: post.title.as_str(),
|
title: post.title.as_str(),
|
||||||
submitter: post.submitter.as_str(),
|
submitter: post.submitter.as_str(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue