|
| 1 | +use crate::out; |
| 2 | +use crate::store::Store; |
| 3 | +use crate::Cli; |
| 4 | +use anyhow::Result; |
| 5 | +use clap::Args; |
| 6 | +use std::io::{self, Write}; |
| 7 | + |
| 8 | +#[derive(Args, Debug, Clone)] |
| 9 | +pub struct ClearArgs { |
| 10 | + /// Only clear chats and messages |
| 11 | + #[arg(long)] |
| 12 | + pub chats: bool, |
| 13 | + |
| 14 | + /// Only clear contacts |
| 15 | + #[arg(long)] |
| 16 | + pub contacts: bool, |
| 17 | + |
| 18 | + /// Skip confirmation prompt |
| 19 | + #[arg(long, short = 'y')] |
| 20 | + pub confirm: bool, |
| 21 | +} |
| 22 | + |
| 23 | +pub async fn run(cli: &Cli, args: &ClearArgs) -> Result<()> { |
| 24 | + let store_dir = cli.store_dir(); |
| 25 | + let store = Store::open(&store_dir).await?; |
| 26 | + |
| 27 | + // Determine what to clear |
| 28 | + let clear_all = !args.chats && !args.contacts; |
| 29 | + let clear_chats = clear_all || args.chats; |
| 30 | + let clear_contacts = clear_all || args.contacts; |
| 31 | + |
| 32 | + // Get counts before clearing |
| 33 | + let counts = get_counts(&store, clear_chats, clear_contacts).await?; |
| 34 | + |
| 35 | + if counts.total() == 0 { |
| 36 | + if cli.json { |
| 37 | + out::write_json(&serde_json::json!({ |
| 38 | + "cleared": false, |
| 39 | + "reason": "nothing to clear" |
| 40 | + }))?; |
| 41 | + } else { |
| 42 | + println!("Nothing to clear."); |
| 43 | + } |
| 44 | + return Ok(()); |
| 45 | + } |
| 46 | + |
| 47 | + // Show what will be deleted |
| 48 | + if !cli.json && !args.confirm { |
| 49 | + println!("This will delete:"); |
| 50 | + if clear_chats { |
| 51 | + println!(" - {} messages", counts.messages); |
| 52 | + println!(" - {} chats", counts.chats); |
| 53 | + println!(" - {} topics", counts.topics); |
| 54 | + } |
| 55 | + if clear_contacts { |
| 56 | + println!(" - {} contacts", counts.contacts); |
| 57 | + } |
| 58 | + println!(); |
| 59 | + print!("Are you sure? [y/N] "); |
| 60 | + io::stdout().flush()?; |
| 61 | + |
| 62 | + let mut input = String::new(); |
| 63 | + io::stdin().read_line(&mut input)?; |
| 64 | + let input = input.trim().to_lowercase(); |
| 65 | + |
| 66 | + if input != "y" && input != "yes" { |
| 67 | + println!("Aborted."); |
| 68 | + return Ok(()); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + // Perform the deletion |
| 73 | + let deleted = clear_tables(&store, clear_chats, clear_contacts).await?; |
| 74 | + |
| 75 | + if cli.json { |
| 76 | + out::write_json(&serde_json::json!({ |
| 77 | + "cleared": true, |
| 78 | + "deleted": { |
| 79 | + "messages": deleted.messages, |
| 80 | + "chats": deleted.chats, |
| 81 | + "topics": deleted.topics, |
| 82 | + "contacts": deleted.contacts |
| 83 | + } |
| 84 | + }))?; |
| 85 | + } else { |
| 86 | + println!("Cleared:"); |
| 87 | + if clear_chats { |
| 88 | + println!(" - {} messages", deleted.messages); |
| 89 | + println!(" - {} chats", deleted.chats); |
| 90 | + println!(" - {} topics", deleted.topics); |
| 91 | + } |
| 92 | + if clear_contacts { |
| 93 | + println!(" - {} contacts", deleted.contacts); |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + Ok(()) |
| 98 | +} |
| 99 | + |
| 100 | +#[derive(Default)] |
| 101 | +struct Counts { |
| 102 | + messages: u64, |
| 103 | + chats: u64, |
| 104 | + topics: u64, |
| 105 | + contacts: u64, |
| 106 | +} |
| 107 | + |
| 108 | +impl Counts { |
| 109 | + fn total(&self) -> u64 { |
| 110 | + self.messages + self.chats + self.topics + self.contacts |
| 111 | + } |
| 112 | +} |
| 113 | + |
| 114 | +async fn get_counts(store: &Store, chats: bool, contacts: bool) -> Result<Counts> { |
| 115 | + let mut counts = Counts::default(); |
| 116 | + |
| 117 | + if chats { |
| 118 | + counts.messages = store.count_messages().await?; |
| 119 | + counts.chats = store.count_chats().await?; |
| 120 | + counts.topics = store.count_topics().await?; |
| 121 | + } |
| 122 | + if contacts { |
| 123 | + counts.contacts = store.count_contacts().await?; |
| 124 | + } |
| 125 | + |
| 126 | + Ok(counts) |
| 127 | +} |
| 128 | + |
| 129 | +async fn clear_tables(store: &Store, chats: bool, contacts: bool) -> Result<Counts> { |
| 130 | + let mut deleted = Counts::default(); |
| 131 | + |
| 132 | + if chats { |
| 133 | + deleted.messages = store.clear_messages().await?; |
| 134 | + deleted.topics = store.clear_topics().await?; |
| 135 | + deleted.chats = store.clear_chats().await?; |
| 136 | + } |
| 137 | + if contacts { |
| 138 | + deleted.contacts = store.clear_contacts().await?; |
| 139 | + } |
| 140 | + |
| 141 | + Ok(deleted) |
| 142 | +} |
0 commit comments