updated the readme, and fixed the tui logic to display the running

operations progress better, also fixed a bug in project promotion where
the project files path and notes path wasn't being added right.
This commit is contained in:
2026-09-02 15:15:27 -05:00
parent dd8fee4297
commit 96672190c4
3 changed files with 61 additions and 19 deletions
+37 -9
View File
@@ -282,25 +282,53 @@ pub fn run_tui(
.wrap(ratatui::widgets::Wrap { trim: false });
f.render_widget(info_paragraph, progress_section[0]);
let mut progress_lines = Vec::new();
let mut color_differnt = false;
state.progress_bars.iter().for_each(|progress| {
if let Ok(status) = progress.read() {
let percentage = status.complete / status.total * 100;
if percentage == 100 {
progress_lines.push(Line::from(Span::styled(
format!("{}:)", status.name),
Style::default().fg(Color::Green),
)));
progress_lines.push(Line::from(Span::styled(
format!(
"{} - {}/{} ({}%)",
status.name, status.complete, status.total, percentage
" {}/{} ({}%)",
status.complete, status.total, percentage
),
Style::default().fg(Color::Green),
)));
} else {
progress_lines.push(Line::from(Span::styled(
format!(
"{} - {}/{} ({}%)",
status.name, status.complete, status.total, percentage
),
Style::default().fg(Color::Magenta),
)));
match color_differnt {
true => {
progress_lines.push(Line::from(Span::styled(
format!("{}:)", status.name),
Style::default().fg(Color::Cyan),
)));
progress_lines.push(Line::from(Span::styled(
format!(
" {}/{} ({}%)",
status.complete, status.total, percentage
),
Style::default().fg(Color::Cyan),
)));
color_differnt = false;
}
false => {
progress_lines.push(Line::from(Span::styled(
format!("{}:)", status.name),
Style::default().fg(Color::Magenta),
)));
progress_lines.push(Line::from(Span::styled(
format!(
" {}/{} ({}%)",
status.complete, status.total, percentage
),
Style::default().fg(Color::Magenta),
)));
color_differnt = true;
}
}
}
}
});
+23 -9
View File
@@ -252,14 +252,14 @@ impl AppState {
.to_string(),
);
self.help.push("parse_scope\nparse the projects general.md notes file for the scope copied from the workbook\n".to_string());
self.help.push("parse_portscan | pps\nParse a services.tsv file exported from cobalt stirke in your current project's files directory".to_string());
self.help.push("parse_portscan | pps\nParse a services.tsv file exported from cobalt stirke in your current project's files directory\n".to_string());
self.help
.push("stop_db\nrestart this project's distrobox".to_string());
self.help.push("rustwitness\nRun a scan on the hosts in the urls.txt file in yoru project files directory that captures screenshots of those urls, optionally through a proxy.".to_string());
self.help.push("portscan\nRun a simple TCP portscan on either the scope for the project, or a given list of ips.\nportscan ip,ip,ip,ip port,port,port,port or portscan port,port,port".to_string());
self.help.push("rustbuster\nRun the Subdomain/Subdirectory bruteforcetool RustBuster (included in tetanus now!) against a given domain name or url.\nrustbuster target,target,target subs=/path/to/subwordlist dirs=/path/to/dirwordlist".to_string());
self.help.push("rustwitness\nRun a scan on the hosts in the urls.txt file in yoru project files directory that captures screenshots of those urls, optionally through a proxy.\n".to_string());
self.help.push("portscan\nRun a simple TCP portscan on either the scope for the project, or a given list of ips.\nportscan ip,ip,ip,ip port,port,port,port or portscan port,port,port\n".to_string());
self.help.push("rustbuster\nRun the Subdomain/Subdirectory bruteforcetool RustBuster (included in tetanus now!) against a given domain name or url.\nrustbuster target,target,target subs=/path/to/subwordlist dirs=/path/to/dirwordlist\n".to_string());
self.help
.push("clear_operations\nClear the progress section of the tool.".to_string());
.push("clear_operations\nClear the completed operation statuses.\n".to_string());
self.help.push("exit\nquit the tool\n".to_string());
self.initialize_modules();
return Ok(());
@@ -1234,9 +1234,14 @@ impl AppState {
format!("{} targets found scanning...", num_dir + num_sub),
)));
let new_progress = Arc::new(RwLock::new(ToolProgress {
name: "rustbuster".to_string(),
name: format!(
"rustbuster - {} {}",
self.projects[self.selected_project].org_name.clone(),
self.projects[self.selected_project].name.clone()
),
total: num_dir + num_sub,
complete: 0,
finished: false,
}));
self.progress_bars.push(new_progress.clone());
self.workers.spawn(move || {
@@ -1314,6 +1319,9 @@ impl AppState {
}
}
});
if let Ok(mut lock) = new_progress.write() {
lock.finished = true;
}
drop(project_clone);
});
} else {
@@ -1349,7 +1357,10 @@ impl AppState {
}
}
"clear_operations" => {
self.progress_bars.clear();
self.progress_bars.retain(|pb| {
let lock = pb.read().unwrap();
!lock.finished
});
}
"exit" => {
self.save_all()?;
@@ -1655,9 +1666,9 @@ impl AppState {
)))?;
let return_string = String::from("[success] Project promoted!");
let mut new_project = self.projects[self.selected_project].clone();
let new_files_path = PathBuf::from(self.config.get("current_files").unwrap())
let mut new_files_path = PathBuf::from(self.config.get("current_files").unwrap())
.join(format!("{}", new_project.org_name));
let new_notes_path = PathBuf::from(self.config.get("current_notes").unwrap())
let mut new_notes_path = PathBuf::from(self.config.get("current_notes").unwrap())
.join(format!("{}", new_project.org_name));
let mut options = CopyOptions::new();
create_dir_all(&new_files_path)?;
@@ -1671,6 +1682,8 @@ impl AppState {
)))?;
remove_dir_all(&new_project.files)?;
remove_dir_all(&new_project.notes)?;
new_files_path.push(&new_project.name);
new_notes_path.push(&new_project.name);
new_project.files(new_files_path.clone());
new_project.notes(new_notes_path.clone());
new_project.current = true;
@@ -3312,4 +3325,5 @@ struct ToolProgress {
name: String,
total: usize,
complete: usize,
finished: bool,
}