use crate::common::database::LibtorrentResumeData;
use crate::common::fastresume::Fastresume;
use crate::config::Config;
use crate::db::query;
use rusqlite::{named_params, Connection};
use std::error::Error;
#[derive(Debug)]
pub struct TrackerUrl {
pub old: String,
pub new: String,
}
pub fn change_tracker_url(
db: &Connection,
tracker_url: &TrackerUrl,
config: &Config,
) -> Result<(), Box<dyn Error>> {
println!(
"Tracker url: replacing '{}' with '{}'",
tracker_url.old, tracker_url.new
);
let all_torrents = query::fetch_all_torrents::<LibtorrentResumeData>(
db,
"
SELECT id, torrent_id, libtorrent_resume_data
FROM torrents
",
)?;
let mut num_torrents_updated = 0;
for torrent in all_torrents {
let mut trigger_update = false;
let bencoded_resume_data = torrent.libtorrent_resume_data.as_slice();
let mut resume_data: Fastresume = serde_bencode::from_bytes(bencoded_resume_data)?;
let mut updated_trackers: Vec<Vec<String>> = Vec::new();
resume_data.trackers.iter().for_each(|outer| {
let mut tracker_list: Vec<String> = Vec::new();
outer.iter().for_each(|tracker| {
if tracker.contains(&tracker_url.old) {
trigger_update = true;
}
tracker_list.push(tracker.replace(&tracker_url.old, &tracker_url.new));
});
updated_trackers.push(tracker_list);
});
resume_data.trackers = updated_trackers;
if trigger_update {
let mut update_stmt = db.prepare(
"
UPDATE torrents
SET libtorrent_resume_data = :lrd
WHERE id = :id
RETURNING torrent_id;
",
)?;
update_stmt.query_row(
named_params! {":lrd": serde_bencode::to_bytes(&resume_data)?, ":id": torrent.id},
|row| {
let updated_row_id = row.get::<usize, String>(0)?;
if config.verbose {
println!("Tracker url: updated tracker URLs for {}", updated_row_id);
println!(
"{}: new tracker urls are {:?}",
updated_row_id, resume_data.trackers
);
}
num_torrents_updated += 1;
Ok(())
},
)?;
}
}
match num_torrents_updated {
0 => print!("Tracker url: no torrents were updated"),
1 => println!("Tracker url: 1 torrent was updated"),
_ => println!(
"Tracker url: {} torrents were updated",
num_torrents_updated
),
}
Ok(())
}