diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 3658eea17..4a04380e0 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -4176,7 +4176,7 @@ pub unsafe extern "C" fn dc_backup_provider_qr_svg( let ctx = &*context; let provider = &*provider; block_on(async move { - generate_backup_qr(ctx, provider.qr()) + generate_backup_qr(ctx, &provider.qr()) .await .unwrap_or_default() .strdup() diff --git a/deltachat-jsonrpc/src/api/mod.rs b/deltachat-jsonrpc/src/api/mod.rs index 9df681cb3..a2a1aaf2e 100644 --- a/deltachat-jsonrpc/src/api/mod.rs +++ b/deltachat-jsonrpc/src/api/mod.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::path::Path; use std::sync::Arc; use std::{collections::HashMap, str::FromStr}; @@ -22,7 +23,7 @@ use deltachat::{ }, provider::get_provider_info, qr, - qr_code_generator::get_securejoin_qr_svg, + qr_code_generator::{generate_backup_qr, get_securejoin_qr_svg}, reaction::send_reaction, securejoin, stock_str::StockMessage, @@ -1336,6 +1337,40 @@ impl CommandApi { .await } + /// Starts to provide the backup for remote devices to retrieve. + /// + /// Can be cancelled by stopping the ongoing process. Success or failure can be tracked + /// via the `ImexProgress` event which should either reach `1000` for success or `0` for + /// failure. + /// + /// This **stops IO**. After completion `start_io` must be called to restart IO. + /// + /// Returns the QR code as a rendered SVG image. + async fn provide_backup(&self, account_id: u32, path: String) -> Result { + let ctx = self.get_context(account_id).await?; + ctx.stop_io().await; + let provider = imex::BackupProvider::prepare(&ctx, Path::new(&path)).await?; + let qr = provider.qr(); + let svg = match generate_backup_qr(&ctx, &qr).await { + Ok(svg) => svg, + Err(err) => { + ctx.stop_ongoing().await; + return Err(err); + } + }; + Ok(svg) + } + + /// Gets a backup from a remote provider. + /// + /// Can be cancelled by stopping the ongoing process. + async fn get_backup(&self, account_id: u32, qr_text: String) -> Result<()> { + let ctx = self.get_context(account_id).await?; + let qr = qr::check_qr(&ctx, &qr_text).await?; + imex::get_backup(&ctx, qr).await?; + Ok(()) + } + // --------------------------------------------- // connectivity // --------------------------------------------- diff --git a/deltachat-jsonrpc/src/api/types/qr.rs b/deltachat-jsonrpc/src/api/types/qr.rs index 143792477..607b495ec 100644 --- a/deltachat-jsonrpc/src/api/types/qr.rs +++ b/deltachat-jsonrpc/src/api/types/qr.rs @@ -33,7 +33,7 @@ pub enum QrObject { domain: String, }, Backup { - ticket: Vec, + ticket: String, }, WebrtcInstance { domain: String, @@ -130,7 +130,7 @@ impl From for QrObject { Qr::FprWithoutAddr { fingerprint } => QrObject::FprWithoutAddr { fingerprint }, Qr::Account { domain } => QrObject::Account { domain }, Qr::Backup { ticket } => QrObject::Backup { - ticket: ticket.to_bytes(), + ticket: ticket.to_string(), }, Qr::WebrtcInstance { domain, diff --git a/deltachat-repl/src/cmdline.rs b/deltachat-repl/src/cmdline.rs index d94c04a47..42c7b0595 100644 --- a/deltachat-repl/src/cmdline.rs +++ b/deltachat-repl/src/cmdline.rs @@ -493,7 +493,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu let dir = tdir.path(); let provider = BackupProvider::prepare(&context, dir).await?; let qr = provider.qr(); - let rendered = deltachat::qr_code_generator::generate_backup_qr(&context, qr).await?; + let rendered = deltachat::qr_code_generator::generate_backup_qr(&context, &qr).await?; let file = dir.join("qr.svg"); tokio::fs::write(&file, rendered).await?; println!("The QR code is at: {}", file.display()); diff --git a/src/qr_code_generator.rs b/src/qr_code_generator.rs index c6f384cf5..cb1cc4ce5 100644 --- a/src/qr_code_generator.rs +++ b/src/qr_code_generator.rs @@ -56,7 +56,7 @@ async fn generate_verification_qr(context: &Context) -> Result { ) } -pub async fn generate_backup_qr(context: &Context, qr: Qr) -> Result { +pub async fn generate_backup_qr(context: &Context, qr: &Qr) -> Result { let Qr::Backup { ticket } = qr else { bail!("QR code not a backup"); }; @@ -325,7 +325,7 @@ mod tests { let qr = provider.qr(); println!("{}", format_backup(&qr).unwrap()); - let rendered = generate_backup_qr(&ctx, qr).await.unwrap(); + let rendered = generate_backup_qr(&ctx, &qr).await.unwrap(); tokio::fs::write(dir.join("qr.svg"), &rendered) .await .unwrap();