Skip to content

Commit 4194873

Browse files
committed
Added simple dump and stats commands.
1 parent f0f124e commit 4194873

File tree

6 files changed

+141
-65
lines changed

6 files changed

+141
-65
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ version = "0.3.1"
66
readme = "README.md"
77
description = "Session Buddy Helper"
88
homepage = "https://www.asdf.cx/sbh"
9-
authors = ["René Wilhelm <[email protected]>"]
9+
authors = ["René <[email protected]>"]
1010
keywords = ["chrome", "extension", "cli"]
1111
repository = "https://github.com/rxw1/sbh"
1212
categories = ["command-line-utilities"]

src/args/mod.rs renamed to src/args.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ pub struct Args {
1111

1212
#[derive(Subcommand, Debug)]
1313
pub enum Action {
14+
/// Dump database to stdout
15+
Dump {
16+
/// Dump all URLs
17+
#[arg()]
18+
path: PathBuf
19+
},
20+
21+
/// Print database statistics
22+
Stats {
23+
/// Path to search for databases
24+
#[arg()]
25+
path: PathBuf
26+
},
27+
1428
/// Search for Session Buddy databases and print out their path
1529
Search {
1630
/// Path to search for databases
@@ -22,7 +36,7 @@ pub enum Action {
2236
Backup {
2337
/// Database to backup
2438
#[arg(value_name = "DATABASE")]
25-
db: PathBuf,
39+
path: PathBuf,
2640

2741
/// Output <FILENAME>
2842
#[arg(short, long, value_name = "FILENAME")]
@@ -33,7 +47,7 @@ pub enum Action {
3347
Import {
3448
/// Path to the database where the data should be imported to
3549
#[arg(short, long)]
36-
database: PathBuf,
50+
path: PathBuf,
3751

3852
/// File that should be imported. Can be a JSON file exported
3953
/// by the Session Buddy extension or another database

src/main.rs

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use clap::Parser;
2+
use sbh::session_buddy::settings::get_datetime_value_setting;
3+
use sbh::session_buddy::settings::get_string_value_setting;
24
use serde::ser::StdError;
35

46
use log::{error, info};
@@ -10,7 +12,50 @@ async fn main() -> Result<(), Box<dyn StdError>> {
1012
pretty_env_logger::init();
1113
let args = Args::parse();
1214
match args.action {
13-
Action::Backup { db, out } => match database::backup(&db, out).await {
15+
Action::Dump { path } => {
16+
for session in database::saved_sessions(&path).await? {
17+
for window in session.windows.iter() {
18+
match &window.tabs {
19+
Some(tabs) => {
20+
for tab in tabs.iter() {
21+
match &tab.url {
22+
Some(url) => {
23+
println!("{}", url);
24+
}
25+
None => {}
26+
}
27+
}
28+
}
29+
None => {}
30+
}
31+
}
32+
}
33+
}
34+
35+
Action::Stats { path } => {
36+
let installation_id =
37+
get_string_value_setting(&path, "Settings", "installationID").await?;
38+
39+
let installation_date =
40+
get_datetime_value_setting(&path, "Settings", "installationTimeStamp").await?;
41+
42+
let sessions = database::saved_sessions(&path).await?;
43+
44+
let session_count = sessions.len();
45+
46+
let window_count: i32 = sessions.iter().map(|s| s.count_windows()).sum();
47+
48+
let tab_count: i32 = sessions.iter().map(|s| s.count_tabs()).sum();
49+
50+
println!("Path: {}", path.display());
51+
println!("Installation ID: {}", installation_id);
52+
println!("Installation Date: {}", installation_date);
53+
println!("Tabs: {:>5}", tab_count);
54+
println!("Windows: {:>5}", window_count);
55+
println!("Sessions: {:>5}", session_count);
56+
}
57+
58+
Action::Backup { path, out } => match database::backup(&path, out).await {
1459
Ok(_) => {
1560
info!("Database created");
1661
}
@@ -37,26 +82,24 @@ async fn main() -> Result<(), Box<dyn StdError>> {
3782
}
3883
}
3984

40-
Action::Import { database, files } => {
41-
match database::collect_saved_sessions(&files).await {
42-
Ok(sessions) => {
43-
let mut conn = database::connect(&database).await?;
44-
match database::import(&mut conn, &sessions).await {
45-
Ok(()) => {
46-
info!("Imported {} sessions", sessions.len());
47-
}
48-
Err(e) => {
49-
error!("{:?}", e);
50-
std::process::exit(1)
51-
}
52-
};
53-
}
54-
Err(e) => {
55-
error!("{:?}", e);
56-
std::process::exit(1)
57-
}
85+
Action::Import { path, files } => match database::collect_saved_sessions(&files).await {
86+
Ok(sessions) => {
87+
let mut conn = database::connect(&path).await?;
88+
match database::import(&mut conn, &sessions).await {
89+
Ok(()) => {
90+
info!("Imported {} sessions", sessions.len());
91+
}
92+
Err(e) => {
93+
error!("{:?}", e);
94+
std::process::exit(1)
95+
}
96+
};
5897
}
59-
}
98+
Err(e) => {
99+
error!("{:?}", e);
100+
std::process::exit(1)
101+
}
102+
},
60103

61104
Action::New { path } => match database::create(&path).await {
62105
Ok(result) => {

src/session_buddy/backup.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use serde::ser::StdError;
66
use serde::Deserialize;
77
use serde::Serialize;
88

9-
use crate::session_buddy::session::get_saved_sessions;
9+
use crate::session_buddy::database;
1010
use crate::session_buddy::session::SavedSession;
1111
use crate::session_buddy::settings::get_datetime_value_setting;
1212
use crate::session_buddy::settings::get_string_value_setting;
@@ -75,7 +75,7 @@ impl Backup {
7575

7676
// Saved sessions
7777
self.sessions.extend(
78-
get_saved_sessions(db)
78+
database::saved_sessions(db)
7979
.await?
8080
//.iter()
8181
//.map(SavedSession::from)

src/session_buddy/database.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::io::{BufWriter, Write};
44
use std::path::{Path, PathBuf};
55
use std::str::FromStr;
66

7+
use chrono::{DateTime, Utc};
78
use log::info;
89
use serde::ser::StdError;
910
use sqlx::sqlite::{SqliteConnectOptions, SqliteQueryResult};
@@ -13,11 +14,37 @@ use crate::chrome::get_path;
1314
use crate::util::get_output_filename;
1415

1516
use super::backup::Backup;
16-
use super::session::SavedSession;
17+
use super::session::{PreviousSession, SavedSession};
1718

1819
// Key "tags" is present on SavedSessions in the database
1920
// but not in JSON backups. Not ok.
2021

22+
#[derive(Default)]
23+
pub struct Stats {
24+
pub sessions: i32,
25+
pub tabs: i32,
26+
pub windows: i32,
27+
pub created: DateTime<Utc>,
28+
pub modified: DateTime<Utc>,
29+
pub atime: DateTime<Utc>,
30+
pub mtime: DateTime<Utc>,
31+
pub ctime: DateTime<Utc>,
32+
pub newest_session: DateTime<Utc>,
33+
pub oldest_session: DateTime<Utc>,
34+
pub duplicate_urls: i32
35+
}
36+
37+
//struct SessionStats {}
38+
//struct TabStats {}
39+
40+
pub async fn stats(path: &Path) -> Result<Stats, Box<dyn StdError>> {
41+
let backup = Backup::new(path).await?;
42+
println!("{}", serde_json::to_string(&backup).unwrap());
43+
Ok(Stats {
44+
..Default::default()
45+
})
46+
}
47+
2148
/// Get a new connection to a SQLite database.
2249
pub async fn connect(filename: &Path) -> Result<SqliteConnection, sqlx::Error> {
2350
SqliteConnectOptions::from_str(format!("sqlite://{}", filename.display()).as_str())?
@@ -196,6 +223,27 @@ pub async fn search(basepath: Option<PathBuf>) -> Result<Vec<PathBuf>, Box<dyn E
196223
Ok(dbs)
197224
}
198225

226+
227+
pub async fn saved_sessions(db: &Path) -> Result<Vec<SavedSession>, Box<dyn StdError>> {
228+
let mut conn = connect(db).await?;
229+
230+
Ok(
231+
sqlx::query_as::<_, SavedSession>("SELECT * FROM SavedSessions")
232+
.fetch_all(&mut conn)
233+
.await?
234+
)
235+
}
236+
237+
pub async fn previous_sessions(db: &Path) -> Result<Vec<PreviousSession>, Box<dyn StdError>> {
238+
let mut conn = connect(db).await?;
239+
240+
Ok(
241+
sqlx::query_as::<_, PreviousSession>("SELECT * FROM PreviousSessions")
242+
.fetch_all(&mut conn)
243+
.await?
244+
)
245+
}
246+
199247
const SCHEMA: &str = r#"
200248
CREATE TABLE Settings (
201249
key TEXT PRIMARY KEY,

src/session_buddy/session.rs

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
use sqlx::types::JsonValue;
21
use std::convert::From;
3-
use std::path::Path;
42

5-
use log::warn;
6-
use serde::ser::StdError;
73
use serde::Deserialize;
84
use serde::Serialize;
95
use sqlx::types::chrono::DateTime;
106
use sqlx::types::chrono::Utc;
117
use sqlx::types::Json;
12-
use sqlx::Connection;
13-
use sqlx::SqliteConnection;
8+
use sqlx::types::JsonValue;
149

1510
use crate::chrome::window::Window;
1611

@@ -31,9 +26,12 @@ pub struct SavedSession {
3126

3227
// Key "gid" is present on SavedSessions in JSON exports but not in the database. Skip when
3328
// running INSERT statements on the database.
34-
pub gid: String,
29+
#[sqlx(default)]
30+
#[serde(default, skip_serializing_if = "Option::is_none")]
31+
pub gid: Option<String>,
3532

3633
// Key "type" is present on SavedSession in JSON exports but not in the database. Actually ok.
34+
#[sqlx(default, rename = "type")]
3735
#[serde(rename = "type")]
3836
pub type_: String,
3937

@@ -79,6 +77,11 @@ pub struct SavedSession {
7977
pub filtered_tab_count: i32
8078
}
8179

80+
//impl From<&Path> for Vec<SavedSession> {
81+
// fn from(s: &Path) {
82+
// }
83+
//}
84+
8285
impl SavedSession {
8386
// TODO Implement functions for filtered window/tab count
8487

@@ -124,35 +127,3 @@ pub struct PreviousSession {
124127
unfiltered_tab_count: i32,
125128
filtered_tab_count: i32
126129
}
127-
128-
// TODO Dry up
129-
130-
pub async fn get_saved_sessions(db: &Path) -> Result<Vec<SavedSession>, Box<dyn StdError>> {
131-
if !db.exists() {
132-
warn!("Database file not found");
133-
std::process::exit(1)
134-
}
135-
136-
let mut conn = SqliteConnection::connect(db.to_str().expect("[102] BAD DB PATH")).await?;
137-
138-
Ok(
139-
sqlx::query_as::<_, SavedSession>("SELECT * FROM SavedSessions")
140-
.fetch_all(&mut conn)
141-
.await?
142-
)
143-
}
144-
145-
pub async fn get_previous_sessions(db: &Path) -> Result<Vec<PreviousSession>, Box<dyn StdError>> {
146-
if !db.exists() {
147-
warn!("Database file not found");
148-
std::process::exit(1)
149-
}
150-
151-
let mut conn = SqliteConnection::connect(db.to_str().expect("[382] BAD DB PATH")).await?;
152-
153-
Ok(
154-
sqlx::query_as::<_, PreviousSession>("SELECT * FROM PreviousSessions")
155-
.fetch_all(&mut conn)
156-
.await?
157-
)
158-
}

0 commit comments

Comments
 (0)