/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use clap::{Parser, Subcommand}; use std::io::{self, Write}; use relay::RelayClient; #[derive(Debug, Parser)] #[command(name = "relay", about = "CLI tool for interacting with Mozilla Relay", long_about = None)] struct Cli { #[arg(short, long, action)] verbose: bool, #[command(subcommand)] command: Commands, } #[derive(Debug, Subcommand)] enum Commands { /// Fetch all Relay addresses Fetch, /// Fetch user profile information Profile, } fn main() -> anyhow::Result<()> { let cli = Cli::parse(); init_logging(&cli); viaduct_hyper::viaduct_init_backend_hyper()?; let token = prompt_token()?; let client = RelayClient::new("https://relay.firefox.com".to_string(), Some(token)); match cli.command { Commands::Fetch => fetch_addresses(client?), Commands::Profile => fetch_profile(client?), } } fn init_logging(cli: &Cli) { let log_filter = if cli.verbose { "relay=trace" } else { "relay=info" }; cli_support::init_logging_with(log_filter); } fn prompt_token() -> anyhow::Result { println!( "See https://github.com/mozilla/fx-private-relay/blob/main/docs/api_auth.md#debugging-tip" ); print!("Enter your Relay auth token: "); io::stdout().flush()?; let mut token = String::new(); io::stdin().read_line(&mut token)?; Ok(token.trim().to_string()) } fn fetch_addresses(client: RelayClient) -> anyhow::Result<()> { match client.fetch_addresses() { Ok(addresses) => { println!("Fetched {} addresses:", addresses.len()); for address in addresses { println!("{:#?}", address); } } Err(e) => { eprintln!("Failed to fetch addresses: {:?}", e); } } Ok(()) } fn fetch_profile(client: RelayClient) -> anyhow::Result<()> { match client.fetch_profile() { Ok(profile) => { println!("User Profile:"); println!(" ID: {}", profile.id); println!(" Premium: {}", profile.has_premium); println!(" Phone: {}", profile.has_phone); println!(" VPN: {}", profile.has_vpn); println!(" Total Masks: {}", profile.total_masks); println!(" At Mask Limit: {}", profile.at_mask_limit); println!(" Emails Forwarded: {}", profile.emails_forwarded); println!(" Emails Blocked: {}", profile.emails_blocked); println!(" Emails Replied: {}", profile.emails_replied); println!(" Trackers Blocked: {}", profile.level_one_trackers_blocked); if let Some(subdomain) = profile.subdomain { println!(" Subdomain: {}", subdomain); } if let Some(date_subscribed) = profile.date_subscribed { println!(" Subscribed Since: {}", date_subscribed); } } Err(e) => { eprintln!("Failed to fetch profile: {:?}", e); } } Ok(()) }