Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ rust-ini = { version = "^0.21" }
which = "8"
duct = "1"
clap = "^4"
clap_complete_command = "0.6.1"
strum = "0.27"

decrypt-cookies = { path = "./crates/decrypt-cookies", version = "0.8.0" }
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ cargo install tidy-browser
tidy-browser -a
cd results

# Get Chrome cookie and login info
tidy-browser chromium -n Chrome -v cookie,login
cd results

# Filter by host/domain
tidy-browser -a --host github.com
cd results
Expand All @@ -29,6 +33,13 @@ tidy-browser binary-cookies -i ~/Library/Containers/com.apple.Safari/Data/Librar
cat ./binary_cookies.csv
```

## Shell completion

```bash
eval $(tidy-browser completions zsh)
eval $(tidy-browser completions <your shell>)
```

## Core crate

[decrypt-cookies](./crates/decrypt-cookies)
Expand Down
1 change: 1 addition & 0 deletions crates/tidy-browser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Subcommand: binary-cookies
- Output format json, jsonlines
- Generate shell completions

## [0.2.0] - 2025-07-27

Expand Down
1 change: 1 addition & 0 deletions crates/tidy-browser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ exclude = ["CHANGELOG.md", "examples", "tests/"]
[dependencies]
binary-cookies = { workspace = true, features = ["csv", "serde", "sync"] }
clap = { workspace = true, features = ["derive"] }
clap_complete_command = { workspace = true }
decrypt-cookies = { workspace = true, features = ["serde"] }
rayon = { workspace = true }
serde = { workspace = true }
Expand Down
55 changes: 31 additions & 24 deletions crates/tidy-browser/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@ use std::path::PathBuf;

use clap::{
builder::{IntoResettable, OsStr, Resettable},
ArgAction,
ArgAction, ValueHint,
};

#[derive(Clone)]
#[derive(Debug)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[derive(clap::Parser)]
pub struct Args {
#[command(subcommand)]
pub core: Option<Core>,

#[arg(short, long, default_value("results"), verbatim_doc_comment)]
pub cmd: Option<SubCmd>,

#[arg(
short,
long,
default_value("results"),
verbatim_doc_comment,
value_hint(ValueHint::DirPath)
)]
/// Specify output dir
/// binary-cookies ignore the arg
pub output_dir: PathBuf,
Expand All @@ -22,11 +27,11 @@ pub struct Args {
/// All browsers data
pub all_browsers: bool,

#[arg(long, default_value(","))]
#[arg(long, default_value(","), value_hint(ValueHint::Other))]
/// Csv separator
pub sep: String,

#[arg(long)]
#[arg(long, id("domain"), value_hint(ValueHint::Url))]
/// Filter by host/domain
pub host: Option<String>,

Expand All @@ -38,7 +43,6 @@ pub struct Args {
#[derive(Clone, Copy)]
#[derive(Debug)]
#[derive(Default)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum Format {
#[default]
Csv,
Expand Down Expand Up @@ -71,9 +75,8 @@ impl IntoResettable<OsStr> for Format {

#[derive(Clone)]
#[derive(Debug)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[derive(clap::Subcommand)]
pub enum Core {
pub enum SubCmd {
/// Chromium based
Chromium(ChromiumArgs),
/// Firefox based
Expand All @@ -83,6 +86,10 @@ pub enum Core {
#[cfg(target_os = "macos")]
/// Safari
Safari(SafariArgs),
/// Generates completions for the specified SHELL, sends them to `stdout` and exits.
Completions {
shell: clap_complete_command::Shell,
},
}

#[derive(Clone, Copy)]
Expand All @@ -107,7 +114,7 @@ pub struct SafariArgs {
/// Only support cookie
pub values: Vec<Value>,

#[arg(long)]
#[arg(long, value_hint(ValueHint::FilePath))]
pub cookies_path: Option<PathBuf>,
}

Expand All @@ -119,20 +126,20 @@ pub struct ChromiumArgs {
#[arg(short, long)]
pub name: ChromiumName,

#[arg(long, id("DIR"), verbatim_doc_comment)]
#[arg(long, id("DIR"), verbatim_doc_comment, value_hint(ValueHint::DirPath))]
/// When browser is started with `--user-data-dir=DIR Specify the directory that user data (your "profile") is kept in.`
#[cfg_attr(target_os = "linux", doc = "[default value: ~/.config/google-chrome]")]
#[cfg_attr(target_os = "linux", doc = "[example value: ~/.config/google-chrome]")]
#[cfg_attr(
target_os = "macos",
doc = "[default value: ~/Library/Application Support/Google/Chrome]"
doc = "[example value: ~/Library/Application Support/Google/Chrome]"
)]
#[cfg_attr(
target_os = "windows",
doc = r"[default value: ~\AppData\Local\Google\Chrome\User Data]"
doc = r"[example value: ~\AppData\Local\Google\Chrome\User Data]"
)]
pub user_data_dir: Option<PathBuf>,

#[arg(short, long, value_delimiter(','))]
#[arg(short, long, value_delimiter(','), action(ArgAction::Append))]
pub values: Vec<Value>,
}

Expand Down Expand Up @@ -166,20 +173,20 @@ pub struct FirefoxArgs {
#[arg(short, long)]
pub name: FirefoxName,

#[arg(long, id("DIR"))]
#[arg(long, id("DIR"), value_hint(ValueHint::DirPath))]
/// Browser data dir.
#[cfg_attr(target_os = "linux", doc = "[default value: ~/.mozilla/firefox]")]
#[cfg_attr(target_os = "linux", doc = "[example value: ~/.mozilla/firefox]")]
#[cfg_attr(
target_os = "macos",
doc = "[default value: ~/Library/Application Support/Firefox]"
doc = "[example value: ~/Library/Application Support/Firefox]"
)]
#[cfg_attr(
target_os = "windows",
doc = r"[default value: ~\AppData\Roaming\Mozilla\Firefox]"
doc = r"[example value: ~\AppData\Roaming\Mozilla\Firefox]"
)]
pub base: Option<PathBuf>,

#[arg(short('P'), id("profile"))]
#[arg(short('P'), id("profile"), value_hint(ValueHint::Other))]
/// When browser is started with `-P <profile> Start with <profile>.`
pub profile: Option<String>,

Expand All @@ -189,7 +196,7 @@ pub struct FirefoxArgs {
/// When the arg is used, other args (such as `--base`, `-P`) are ignore.
pub profile_path: Option<PathBuf>,

#[arg(short, long, value_delimiter(','))]
#[arg(short, long, value_delimiter(','), action(ArgAction::Append))]
/// Only support cookie
pub values: Vec<Value>,
}
Expand All @@ -211,8 +218,8 @@ pub enum FirefoxName {
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[derive(clap::Args)]
pub struct BinaryCookiesArgs {
#[arg(short('i'), long)]
#[arg(short('i'), long, value_hint(ValueHint::FilePath))]
pub cookies_path: PathBuf,
#[arg(short, long)]
#[arg(short, long, value_hint(ValueHint::FilePath))]
pub out_file: Option<PathBuf>,
}
21 changes: 14 additions & 7 deletions crates/tidy-browser/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::{collections::HashSet, path::PathBuf, str::FromStr};
use std::{collections::HashSet, io, path::PathBuf, str::FromStr};

use clap::CommandFactory;
use snafu::ResultExt;
use strum::IntoEnumIterator;

use crate::{
args::{self, BinaryCookiesArgs, ChromiumArgs, ChromiumName, FirefoxArgs, FirefoxName, Format},
args::{
self, Args, BinaryCookiesArgs, ChromiumArgs, ChromiumName, FirefoxArgs, FirefoxName, Format,
},
binary_cookies::BinaryCookiesWriter,
chromium::ChromiumBased,
error::{self, Result},
Expand Down Expand Up @@ -83,9 +86,13 @@ pub async fn run_cli(args: crate::args::Args) -> Result<()> {

return Ok(());
}
if let Some(core) = args.core {

if let Some(core) = args.cmd {
match core {
args::Core::Chromium(ChromiumArgs { name, user_data_dir, values }) => {
args::SubCmd::Completions { shell } => {
shell.generate(&mut Args::command(), &mut io::stdout())
},
args::SubCmd::Chromium(ChromiumArgs { name, user_data_dir, values }) => {
ChromiumBased::write_data(
name,
user_data_dir,
Expand All @@ -97,7 +104,7 @@ pub async fn run_cli(args: crate::args::Args) -> Result<()> {
)
.await?;
},
args::Core::Firefox(FirefoxArgs {
args::SubCmd::Firefox(FirefoxArgs {
name,
base,
profile,
Expand All @@ -117,7 +124,7 @@ pub async fn run_cli(args: crate::args::Args) -> Result<()> {
)
.await?
},
args::Core::BinaryCookies(BinaryCookiesArgs { cookies_path, out_file }) => {
args::SubCmd::BinaryCookies(BinaryCookiesArgs { cookies_path, out_file }) => {
BinaryCookiesWriter::write_data(
cookies_path,
out_file.unwrap_or_else(|| match args.out_format {
Expand All @@ -132,7 +139,7 @@ pub async fn run_cli(args: crate::args::Args) -> Result<()> {
)?;
},
#[cfg(target_os = "macos")]
args::Core::Safari(SafariArgs { values, cookies_path }) => {
args::SubCmd::Safari(SafariArgs { values, cookies_path }) => {
SafariBased::write_data(
HashSet::from_iter(values.into_iter()),
cookies_path,
Expand Down
Loading