diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmdline.rs | 18 | ||||
-rw-r--r-- | src/main.rs | 84 |
2 files changed, 102 insertions, 0 deletions
diff --git a/src/cmdline.rs b/src/cmdline.rs new file mode 100644 index 0000000..43adbec --- /dev/null +++ b/src/cmdline.rs @@ -0,0 +1,18 @@ +use std::path::PathBuf; + +use clap::Parser; +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +pub struct Args { + /// Path to browser executable + #[arg(short, long)] + pub browser: PathBuf, + #[arg(short = 'm', long)] + pub dmenu: PathBuf, + /// Location history sqlite database + #[arg(short = 'p', long, default_value = PathBuf::from("~/.mozilla/firefox/11ybm96o.default").into_os_string())] + pub profile: PathBuf, + /// Limit of location history entries to seek + #[arg(short = 'l', long, default_value_t = 100)] + pub limit: usize, +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d3c927d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,84 @@ +mod cmdline; +use clap::Parser; +use cmdline::Args; +use rusqlite::{params, Connection, Result}; +use std::{ + collections::HashSet, + fmt::Display, + fs, + path::{Path, PathBuf}, +}; +use url; +#[derive(Debug)] +struct FirefoxPlace { + id: u64, + url: String, +} +struct NoProfileFoundError {} +impl Display for NoProfileFoundError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "No suitable profile was found") + } +} +fn match_firefox_profile() -> Result<PathBuf, NoProfileFoundError> { + todo!() +} +fn copy_db(root_path: Option<&PathBuf>) -> Option<PathBuf> { + let mut root = if let Some(p) = root_path { + p.clone() + } else { + if let Ok(found_profile_path) = match_firefox_profile() { + found_profile_path + } else { + panic!("thing"); + } + }; + root.push("places.sqlite"); + let tmp_path = PathBuf::from("/tmp/firefox-dmenu-places.db"); + match fs::exists(&root) { + Ok(existence) => { + if !existence { + panic!("[FS] DB does not exist") + } else { + fs::copy(root, &tmp_path); + return Some(tmp_path); + } + } + Err(_) => { + panic!("[FS] something wrong...") + } + }; +} +fn main() -> Result<()> { + let args = Args::parse(); + let path = if let Some(p) = copy_db(Some(&args.profile)) { + p + } else { + panic!("baddddd") + }; + let conn = Connection::open(&path).unwrap(); + let query = format!("SELECT id, url FROM moz_places ORDER BY last_visit_date DESC LIMIT {}", args.limit); + let mut stmt = conn.prepare(&query).unwrap(); + let urls_iter = stmt.query_map([], |row| { + Ok(FirefoxPlace { + id: row.get(0)?, + url: row.get(1)?, + }) + })?; + let mut hosts = HashSet::new(); + for place in urls_iter { + if let Ok(p) = place { + let url = url::Url::parse(&p.url); + if let Ok(u) = url { + if let Some(s) = u.host_str() { + hosts.insert(s.to_string()); + } + } + } + } + for h in hosts { + println!("{}", h); + } + fs::remove_file(&path); + Ok(()) +} |