Skip to content

Commit 58fe8a3

Browse files
authored
feat: Add command for registering magnet link handler (#109)
1 parent 83febfe commit 58fe8a3

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

cli/src/main.rs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
fs::OpenOptions, io::ErrorKind, net::TcpListener, num::ParseIntError, path::PathBuf,
3-
sync::mpsc::SyncSender, time::Duration,
3+
process::Command as ProcessCommand, sync::mpsc::SyncSender, time::Duration,
44
};
55

66
use clap::{Args, Parser};
@@ -150,9 +150,10 @@ struct TorrentInfo {
150150
magnet_link: Option<String>,
151151
}
152152

153-
/// Vortex bittorrent client cli. Fast trackerless torrent downloads using modern io_uring techniques.
153+
/// Vortex bittorrent client cli. Fast trackerless torrent client using modern io_uring techniques.
154154
#[derive(Debug, Parser)]
155155
#[command(version, about, long_about = None)]
156+
#[command(subcommand_negates_reqs = true)]
156157
struct Cli {
157158
/// Port for the listener
158159
#[arg(short, long)]
@@ -175,12 +176,69 @@ struct Cli {
175176
/// Skip use of the DHT node cache and rebuild from bootstrap nodes
176177
#[arg(long)]
177178
skip_dht_cache: bool,
179+
#[command(subcommand)]
180+
command: Option<CliCommand>,
181+
}
182+
183+
#[derive(Debug, clap::Subcommand)]
184+
enum CliCommand {
185+
/// Register vortex-cli as the system-wide magnet link handler
186+
RegisterMagnetHandler,
187+
}
188+
189+
fn register_magnet_handler() -> color_eyre::Result<()> {
190+
let exe_path = std::env::current_exe()
191+
.wrap_err("Failed to determine current executable path")?
192+
.canonicalize()
193+
.wrap_err("Failed to canonicalize executable path")?;
194+
195+
let applications_dir = dirs::data_dir()
196+
.wrap_err("Failed to determine data directory")?
197+
.join("applications");
198+
std::fs::create_dir_all(&applications_dir)
199+
.wrap_err("Failed to create applications directory")?;
200+
201+
let desktop_file = applications_dir.join("vortex-cli.desktop");
202+
let desktop_contents = format!(
203+
"[Desktop Entry]\n\
204+
Type=Application\n\
205+
Name=Vortex\n\
206+
Comment=Fast trackerless torrent client using modern io_uring techniques\n\
207+
Exec={} --magnet-link %u\n\
208+
MimeType=x-scheme-handler/magnet;\n\
209+
NoDisplay=true\n\
210+
Terminal=true\n",
211+
exe_path.display()
212+
);
213+
std::fs::write(&desktop_file, &desktop_contents)
214+
.wrap_err("Failed to write .desktop file for vorex-cli")?;
215+
216+
let status = ProcessCommand::new("xdg-mime")
217+
.args(["default", "vortex-cli.desktop", "x-scheme-handler/magnet"])
218+
.status()
219+
.wrap_err("Failed to run xdg-mime")?;
220+
if !status.success() {
221+
return Err(eyre!("xdg-mime exited with status {status}"));
222+
}
223+
224+
// Best-effort to update the desktop database
225+
let _ = ProcessCommand::new("update-desktop-database")
226+
.arg(&applications_dir)
227+
.status();
228+
229+
println!("Registered vortex-cli as the default magnet link handler.");
230+
println!("Desktop file written to: {}", desktop_file.display());
231+
Ok(())
178232
}
179233

180234
fn main() -> color_eyre::Result<()> {
181235
color_eyre::install()?;
182236
let cli = Cli::parse();
183237

238+
if let Some(CliCommand::RegisterMagnetHandler) = cli.command {
239+
return register_magnet_handler();
240+
}
241+
184242
// load or create config file (auto-creates if doesn't exist)
185243
let mut vortex_config =
186244
config::load_or_create_config(cli.config_file).wrap_err("Failed to load config")?;

0 commit comments

Comments
 (0)