diff --git a/src/import/attachment.rs b/src/import/attachment.rs index 3a45183..f68321f 100644 --- a/src/import/attachment.rs +++ b/src/import/attachment.rs @@ -1,15 +1,17 @@ -use color_eyre::eyre::Context; // -use crate::import::rate_limit::{RateLimitActor, RequestToken}; +use std::path::{Path, PathBuf}; + +use color_eyre::eyre::Context; +use kameo::{actor::ActorRef, mailbox::unbounded::UnboundedMailbox, Actor}; + use crate::{ - ask, e, f, - nextcloud::model::{NextcloudBoardId, NextcloudCardId, NextcloudStackId}, + ask, f, + import::rate_limit::{RateLimitActor, RequestToken}, + nextcloud::model::{Attachment, NextcloudBoardId, NextcloudCardId, NextcloudStackId}, on_actor_start, p, trello::model::{attachment::TrelloAttachment, card::TrelloCardId}, FullCtx, }; -use kameo::actor::ActorRef; -use kameo::{mailbox::unbounded::UnboundedMailbox, Actor}; pub(crate) struct ImportAttachmentActor { ctx: FullCtx, @@ -40,6 +42,39 @@ impl ImportAttachmentActor { rate_limit_actor, } } + + async fn import_attachment(&self, file_name: &Path) -> color_eyre::Result { + let temp_fs = kxio::fs::temp()?; + let file_path = temp_fs.base().join(file_name); + + // - - - download the attachment from trello + ask!(self.rate_limit_actor, RequestToken)?; + let attachment_path = self + .ctx + .trello_client() + .save_attachment( + &self.trello_card_id, + &self.trello_attachment.id, + Some(&file_path), + &self.ctx.temp_fs, + ) + .await + .with_context(|| f!("saving attachment {}", file_path.display()))?; + + // - - - upload the attachment to nextcloud card + tracing::info!("Nextcloud: upload attachment"); + self.ctx + .deck_client() + .add_attachment_to_card( + self.nextcloud_board_id, + self.nextcloud_stack_id, + self.nextcloud_card_id, + &temp_fs.file(&attachment_path), + ) + .await + .result + .with_context(|| f!("adding attachment to card {}", file_path.display())) + } } impl Actor for ImportAttachmentActor { type Mailbox = UnboundedMailbox; @@ -50,61 +85,28 @@ impl Actor for ImportAttachmentActor { ">> Adding attachment: {}", this.trello_attachment.name ); - // - - - download the attachment from trello let file_name = f!( "{}-{}", this.trello_attachment.id, this.trello_attachment.name ); - let file_path = this.ctx.temp_fs.base().join(&file_name); - ask!(this.rate_limit_actor, RequestToken)?; // FIXME: (#6) handle error - let attachment_path = this - .ctx - .trello_client() - .save_attachment( - &this.trello_card_id, - &this.trello_attachment.id, - Some(&file_path), - &this.ctx.temp_fs, - ) - .await - .with_context(|| f!("saving attachment {}", file_path.display()))?; // FIXME: (#6) handle error - let attachment_file = this.ctx.temp_fs.file(&attachment_path); - // - - - upload the attachment to nextcloud card - tracing::info!("Nextcloud: upload attachment"); - let attachment = this - .ctx - .deck_client() - .add_attachment_to_card( - this.nextcloud_board_id, - this.nextcloud_stack_id, - this.nextcloud_card_id, - &attachment_file, - ) - .await - .result - .inspect_err(|e| { - e!( - this.ctx.prt, - ">> Error adding attachment {} to card: {}", - file_path.display(), - e.to_string() - ); - }) - .with_context(|| f!("adding attachment to card {}", file_path.display()))?; // FIXME: (#6) handle error - p!( - this.ctx.prt, - ">> Attachment added: {}:{}", - attachment.id, - attachment.attachment_type, - // attachment.extended_data.mimetype - ); - // delete local copy of attachment - attachment_file - .remove() - .with_context(|| f!("deleting temp file {attachment_file}"))?; // FIXME: (#6) handle error - tracing::info!("ImportAttachmentActor finished"); + match this.import_attachment(&PathBuf::from(file_name)).await { + Ok(attachment) => { + p!( + this.ctx.prt, + ">> Attachment added: {}:{}", + attachment.id, + attachment.attachment_type, + // attachment.extended_data.mimetype + ); + tracing::info!("ImportAttachmentActor finished"); + } + Err(err) => { + tracing::error!(?err); + } + } + Ok(actor_ref.stop_gracefully().await?) }); } diff --git a/src/import/card.rs b/src/import/card.rs index 9b5dd4d..a65a98e 100644 --- a/src/import/card.rs +++ b/src/import/card.rs @@ -1,13 +1,7 @@ // use std::collections::HashMap; -use kameo::{ - actor::{ActorID, ActorRef}, - error::ActorStopReason, - mailbox::unbounded::UnboundedMailbox, - Actor, -}; - +use crate::nextcloud::model::Card; use crate::{ ask, import::{ @@ -27,6 +21,13 @@ use crate::{ }, FullCtx, }; +use kameo::{ + actor::{ActorID, ActorRef}, + error::ActorStopReason, + mailbox::unbounded::UnboundedMailbox, + Actor, +}; +use kxio::Error; pub(crate) struct ImportCardActor { ctx: FullCtx, @@ -73,8 +74,9 @@ impl Actor for ImportCardActor { 0 => None, _ => Some(NextcloudCardDescription::from(&this.trello_card.desc)), }; + tracing::info!("Nextcloud: Create card"); - let nextcloud_card = this + let nextcloud_card_id = match this .ctx .deck_client() .create_card( @@ -84,7 +86,14 @@ impl Actor for ImportCardActor { desc.as_ref(), ) .await - .result?; // FIXME: (#6) handle error + .result + { + Ok(card) => card.id, + Err(err) => { + tracing::error!(?err); + return Ok(actor_ref.stop_gracefully().await?); + } + }; let mut limit = RateLimit::new("labels & attachments", 10, 10.0, this.ctx.now()); @@ -101,7 +110,7 @@ impl Actor for ImportCardActor { this.ctx.clone(), this.nextcloud_board_id, this.nextcloud_stack_id, - nextcloud_card.id, + nextcloud_card_id, trello_label, this.labels_actor_ref.clone(), ) @@ -129,7 +138,7 @@ impl Actor for ImportCardActor { this.ctx.clone(), this.nextcloud_board_id, this.nextcloud_stack_id, - nextcloud_card.id, + nextcloud_card_id, this.trello_card.id.clone(), trello_attachment, this.rate_limit_actor.clone(), diff --git a/src/import/label.rs b/src/import/label.rs index dc51b3d..3e1e880 100644 --- a/src/import/label.rs +++ b/src/import/label.rs @@ -41,17 +41,24 @@ impl Actor for ImportLabelActor { type Mailbox = UnboundedMailbox; on_actor_start!(this, actor_ref, { - let label_id = ask!( + let label_id = match ask!( this.labels_actor_ref, labels::LookupNextcloudLabelId { trello_name: this.trello_label.name.clone(), trello_color: this.trello_label.color.clone() } - )?; // FIXME: (#6) handle error + ) { + Ok(label_id) => label_id, + Err(err) => { + tracing::error!(?err); + return Ok(actor_ref.stop_gracefully().await?); + } + }; // - - - add the label to the nextcloud card tracing::info!("Nextcloud: add label to card"); - this.ctx + match this + .ctx .deck_client() .add_label_to_card( this.nextcloud_board_id, @@ -60,9 +67,11 @@ impl Actor for ImportLabelActor { label_id, ) .await - .result?; // FIXME: (#6) handle error - - tracing::info!("ImportLabelActor finished"); + .result + { + Ok(_) => tracing::info!("ImportLabelActor finished"), + Err(err) => tracing::error!(?err), + } Ok(actor_ref.stop_gracefully().await?) }); } diff --git a/src/import/stack.rs b/src/import/stack.rs index 48ebf48..46baccd 100644 --- a/src/import/stack.rs +++ b/src/import/stack.rs @@ -62,7 +62,10 @@ impl Actor for ImportStackActor { crate::p!(this.ctx.prt, "Importing stack: {}", this.trello_stack.name); // - get the list of trello cards in the stack - ask!(this.rate_limit_actor, RequestToken)?; // FIXME: (#6) handle error + if let Err(err) = ask!(this.rate_limit_actor, RequestToken) { + tracing::error!(?err); + return Ok(actor_ref.stop_gracefully().await?); + } let mut trello_cards = trello_client .list_cards(&TrelloListId::new(this.trello_stack.id.as_ref())) .await @@ -75,7 +78,10 @@ impl Actor for ImportStackActor { // - for each card in the trello stack for trello_card in trello_cards.into_iter() { limit.block_until_token_available(this.ctx.now()).await; - ask!(this.rate_limit_actor, RequestToken)?; // FIXME: (#6) handle error + if let Err(err) = ask!(this.rate_limit_actor, RequestToken) { + tracing::error!(?err); + return Ok(actor_ref.stop_gracefully().await?); + } let trello_card_name = trello_card.name.clone(); let child: ActorRef = spawn_in_thread!( actor_ref.clone(),