From 3d76187c85a66b341bde800599927ed11414029a Mon Sep 17 00:00:00 2001 From: cliffmccarthy <16453869+cliffmccarthy@users.noreply.github.com> Date: Sat, 26 Jul 2025 13:07:37 -0500 Subject: [PATCH 1/3] feat: Add import-vcard and make-vcard commands to repl - Added import-vcard and make-vcard commands to deltachat-repl. These wrap the corresponding import_vcard() and make_vcard() operations from src/contact.rs. Each command takes a file path argument specifying the location of the vCard file to be read or written. The make-vcard command takes one or more IDs to write to the file. - Documented commands in "Using the CLI client" section of README.md. closes #7047 --- README.md | 12 ++++++++++-- deltachat-repl/src/cmdline.rs | 20 ++++++++++++++++++++ deltachat-repl/src/main.rs | 4 +++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f5fb28063f..849f6276d1 100644 --- a/README.md +++ b/README.md @@ -80,18 +80,26 @@ Connect to your mail server (if already configured): > connect ``` -Create a contact: +Export your public key to a vCard file: + +``` +> make-vcard my.vcard 1 +``` + +Create contacts by address or vCard file: ``` > addcontact yourfriends@email.org +> import-vcard keyfriend.vcard ``` List contacts: ``` > listcontacts +Contact#Contact#11: keyfriend@email.org Contact#Contact#Self: Me √ -1 key contacts. +2 key contacts. Contact#Contact#10: yourfriends@email.org 1 address contacts. ``` diff --git a/deltachat-repl/src/cmdline.rs b/deltachat-repl/src/cmdline.rs index a01c16a06c..fde0f863c1 100644 --- a/deltachat-repl/src/cmdline.rs +++ b/deltachat-repl/src/cmdline.rs @@ -403,6 +403,8 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu block \n\ unblock \n\ listblocked\n\ + import-vcard \n\ + make-vcard [contact-id ...]\n\ ======================================Misc.==\n\ getqr []\n\ getqrsvg []\n\ @@ -1218,6 +1220,24 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu log_contactlist(&context, &contacts).await?; println!("{} blocked contacts.", contacts.len()); } + "import-vcard" => { + ensure!(!arg1.is_empty(), "Argument missing."); + let vcard_content = fs::read_to_string(&arg1.to_string()).await?; + let contacts = import_vcard(&context, &vcard_content).await?; + println!("vCard contacts imported to:"); + log_contactlist(&context, &contacts).await?; + } + "make-vcard" => { + ensure!(!arg1.is_empty(), "Argument missing."); + ensure!(!arg2.is_empty(), "Argument missing."); + let mut contact_ids = vec![]; + for x in arg2.split(' ') { + contact_ids.push(ContactId::new(x.parse()?)) + } + let vcard_content = make_vcard(&context, &contact_ids).await?; + fs::write(&arg1.to_string(), vcard_content).await?; + println!("vCard written to: {}", arg1); + } "checkqr" => { ensure!(!arg1.is_empty(), "Argument missing."); let qr = check_qr(&context, arg1).await?; diff --git a/deltachat-repl/src/main.rs b/deltachat-repl/src/main.rs index 1cca2aad2e..8b06cc558e 100644 --- a/deltachat-repl/src/main.rs +++ b/deltachat-repl/src/main.rs @@ -232,7 +232,7 @@ const MESSAGE_COMMANDS: [&str; 10] = [ "delmsg", "react", ]; -const CONTACT_COMMANDS: [&str; 7] = [ +const CONTACT_COMMANDS: [&str; 9] = [ "listcontacts", "addcontact", "contactinfo", @@ -240,6 +240,8 @@ const CONTACT_COMMANDS: [&str; 7] = [ "block", "unblock", "listblocked", + "import-vcard", + "make-vcard", ]; const MISC_COMMANDS: [&str; 14] = [ "getqr", From f030b2317e99905d8892f72c471e6639c34b46a7 Mon Sep 17 00:00:00 2001 From: cliffmccarthy <16453869+cliffmccarthy@users.noreply.github.com> Date: Sun, 27 Jul 2025 13:38:08 -0500 Subject: [PATCH 2/3] feat: Revise import-vcard and make-vcard implementation - In key contact example, use project terminology "key-contact". - Removed unnecessary "to" from import-vcard output. - Use split_whitespace() to separate IDs in make-vcard. - All changes suggested in review by iequidoo. --- README.md | 4 ++-- deltachat-repl/src/cmdline.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 849f6276d1..42a4d0bde5 100644 --- a/README.md +++ b/README.md @@ -90,14 +90,14 @@ Create contacts by address or vCard file: ``` > addcontact yourfriends@email.org -> import-vcard keyfriend.vcard +> import-vcard key-contact.vcard ``` List contacts: ``` > listcontacts -Contact#Contact#11: keyfriend@email.org +Contact#Contact#11: key-contact@email.org Contact#Contact#Self: Me √ 2 key contacts. Contact#Contact#10: yourfriends@email.org diff --git a/deltachat-repl/src/cmdline.rs b/deltachat-repl/src/cmdline.rs index fde0f863c1..ffb2998005 100644 --- a/deltachat-repl/src/cmdline.rs +++ b/deltachat-repl/src/cmdline.rs @@ -1224,14 +1224,14 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu ensure!(!arg1.is_empty(), "Argument missing."); let vcard_content = fs::read_to_string(&arg1.to_string()).await?; let contacts = import_vcard(&context, &vcard_content).await?; - println!("vCard contacts imported to:"); + println!("vCard contacts imported:"); log_contactlist(&context, &contacts).await?; } "make-vcard" => { ensure!(!arg1.is_empty(), "Argument missing."); ensure!(!arg2.is_empty(), "Argument missing."); let mut contact_ids = vec![]; - for x in arg2.split(' ') { + for x in arg2.split_whitespace() { contact_ids.push(ContactId::new(x.parse()?)) } let vcard_content = make_vcard(&context, &contact_ids).await?; From 6e7b66d9c6b0b248eeb0cfc16736f75cccc39035 Mon Sep 17 00:00:00 2001 From: iequidoo <117991069+iequidoo@users.noreply.github.com> Date: Wed, 30 Jul 2025 13:00:51 -0300 Subject: [PATCH 3/3] Update deltachat-repl/src/cmdline.rs --- deltachat-repl/src/cmdline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deltachat-repl/src/cmdline.rs b/deltachat-repl/src/cmdline.rs index ffb2998005..29f11c20fb 100644 --- a/deltachat-repl/src/cmdline.rs +++ b/deltachat-repl/src/cmdline.rs @@ -1236,7 +1236,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu } let vcard_content = make_vcard(&context, &contact_ids).await?; fs::write(&arg1.to_string(), vcard_content).await?; - println!("vCard written to: {}", arg1); + println!("vCard written to: {arg1}"); } "checkqr" => { ensure!(!arg1.is_empty(), "Argument missing.");