Start work on Monitor Album
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
//! Magnet-link resolver backed by librqbit.
|
||||
//!
|
||||
//! Turns a `magnet:` URI into the same bencoded torrent bytes a `.torrent`
|
||||
//! download would yield, by resolving metadata over the BitTorrent DHT and
|
||||
//! the BEP-9 `ut_metadata` peer extension. The bytes are then handed to
|
||||
//! [`crate::torrent_parser::TorrentParser`] so magnet and torrent sources are
|
||||
//! parsed identically.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context, bail};
|
||||
use librqbit::{
|
||||
AddTorrent, AddTorrentOptions, AddTorrentResponse, ListOnlyResponse, Session, SessionOptions,
|
||||
};
|
||||
use tempfile::TempDir;
|
||||
|
||||
const RESOLVE_TIMEOUT: Duration = Duration::from_secs(90);
|
||||
|
||||
pub struct MagnetResolver {
|
||||
session: Arc<Session>,
|
||||
_scratch_dir: TempDir,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for MagnetResolver {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("MagnetResolver").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl MagnetResolver {
|
||||
pub async fn new() -> anyhow::Result<Self> {
|
||||
let scratch_dir = tempfile::TempDir::new()?;
|
||||
let opts = SessionOptions {
|
||||
disable_dht_persistence: true,
|
||||
persistence: None,
|
||||
enable_upnp_port_forwarding: false,
|
||||
..Default::default()
|
||||
};
|
||||
let session = Session::new_with_opts(scratch_dir.path().to_path_buf(), opts).await?;
|
||||
Ok(Self {
|
||||
session,
|
||||
_scratch_dir: scratch_dir,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn resolve(&self, magnet: &str) -> anyhow::Result<Vec<u8>> {
|
||||
let added = tokio::time::timeout(
|
||||
RESOLVE_TIMEOUT,
|
||||
self.session.add_torrent(
|
||||
AddTorrent::from_url(magnet),
|
||||
Some(AddTorrentOptions {
|
||||
list_only: true,
|
||||
..Default::default()
|
||||
}),
|
||||
),
|
||||
)
|
||||
.await
|
||||
.context("magnet resolution timed out (>90s, likely no peers)")?
|
||||
.context("error adding magnet to session")?;
|
||||
|
||||
match added {
|
||||
AddTorrentResponse::ListOnly(ListOnlyResponse { torrent_bytes, .. }) => {
|
||||
Ok(torrent_bytes.to_vec())
|
||||
}
|
||||
AddTorrentResponse::AlreadyManaged(_, handle) => {
|
||||
handle.with_metadata(|m| m.torrent_bytes.to_vec())
|
||||
}
|
||||
AddTorrentResponse::Added(_, _) => {
|
||||
bail!("torrent unexpectedly added under list_only")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user