feat: write downloaded attachments to temp directory
This commit is contained in:
parent
fa7d565238
commit
0023e2aa70
18 changed files with 49 additions and 14 deletions
|
@ -1,6 +1,4 @@
|
||||||
//
|
//
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use kameo::{mailbox::unbounded::UnboundedMailbox, Actor};
|
use kameo::{mailbox::unbounded::UnboundedMailbox, Actor};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -47,16 +45,21 @@ impl Actor for ImportAttachmentActor {
|
||||||
this.trello_attachment.name
|
this.trello_attachment.name
|
||||||
);
|
);
|
||||||
// - - - download the attachment from trello
|
// - - - download the attachment from trello
|
||||||
|
let dir_path = this.ctx.temp_fs.base().join(&*this.trello_attachment.id);
|
||||||
|
let dir = this.ctx.temp_fs.dir(&dir_path);
|
||||||
|
dir.create()?;
|
||||||
|
let file_path = dir_path.join(&*this.trello_attachment.name);
|
||||||
let attachment_path = this
|
let attachment_path = this
|
||||||
.ctx
|
.ctx
|
||||||
.trello_client()
|
.trello_client()
|
||||||
.save_attachment(
|
.save_attachment(
|
||||||
&this.trello_card_id,
|
&this.trello_card_id,
|
||||||
&this.trello_attachment.id,
|
&this.trello_attachment.id,
|
||||||
Some(&PathBuf::from(&(*this.trello_attachment.id))),
|
Some(&file_path),
|
||||||
|
&this.ctx.temp_fs,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let attachment_file = this.ctx.fs.file(&attachment_path);
|
let attachment_file = this.ctx.temp_fs.file(&attachment_path);
|
||||||
// - - - upload the attachment to nextcloud card
|
// - - - upload the attachment to nextcloud card
|
||||||
let attachment = this
|
let attachment = this
|
||||||
.ctx
|
.ctx
|
||||||
|
@ -78,6 +81,7 @@ impl Actor for ImportAttachmentActor {
|
||||||
);
|
);
|
||||||
// delete local copy of attachment
|
// delete local copy of attachment
|
||||||
attachment_file.remove()?;
|
attachment_file.remove()?;
|
||||||
|
dir.remove()?;
|
||||||
|
|
||||||
Ok(actor_ref.stop_gracefully().await?)
|
Ok(actor_ref.stop_gracefully().await?)
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
//
|
//
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::{nextcloud::client::DeckClient, trello::client::TrelloClient};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use color_eyre::eyre::eyre;
|
use color_eyre::eyre::eyre;
|
||||||
use config::AppConfig;
|
use config::AppConfig;
|
||||||
|
use kxio::fs::TempFileSystem;
|
||||||
use kxio::{fs::FileSystem, kxeprintln as e, kxprintln as p, net::Net, print::Printer};
|
use kxio::{fs::FileSystem, kxeprintln as e, kxprintln as p, net::Net, print::Printer};
|
||||||
|
|
||||||
use crate::{nextcloud::client::DeckClient, trello::client::TrelloClient};
|
|
||||||
|
|
||||||
use execute::Execute;
|
use execute::Execute;
|
||||||
|
|
||||||
mod api_result;
|
mod api_result;
|
||||||
|
@ -81,6 +81,7 @@ impl From<PathBuf> for Ctx {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct FullCtx {
|
pub(crate) struct FullCtx {
|
||||||
pub fs: FileSystem,
|
pub fs: FileSystem,
|
||||||
|
pub temp_fs: TempFileSystem,
|
||||||
pub net: Net,
|
pub net: Net,
|
||||||
pub prt: Printer,
|
pub prt: Printer,
|
||||||
pub cfg: AppConfig,
|
pub cfg: AppConfig,
|
||||||
|
@ -128,6 +129,7 @@ pub async fn run(ctx: &Ctx, commands: &Commands) -> color_eyre::Result<()> {
|
||||||
.command
|
.command
|
||||||
.execute(&FullCtx {
|
.execute(&FullCtx {
|
||||||
fs: ctx.fs.clone(),
|
fs: ctx.fs.clone(),
|
||||||
|
temp_fs: kxio::fs::temp()?,
|
||||||
net: ctx.net.clone(),
|
net: ctx.net.clone(),
|
||||||
prt: ctx.prt.clone(),
|
prt: ctx.prt.clone(),
|
||||||
cfg,
|
cfg,
|
||||||
|
|
|
@ -34,6 +34,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -54,6 +54,7 @@ fn ctx_path() -> (FullCtx, PathBuf, TempFileSystem) {
|
||||||
(
|
(
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: temp_fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -42,6 +42,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -33,6 +33,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -38,6 +38,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -21,6 +21,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -63,6 +63,7 @@ async fn test_full_ctx_clients() -> Result<()> {
|
||||||
|
|
||||||
let full_ctx = FullCtx {
|
let full_ctx = FullCtx {
|
||||||
fs: ctx.fs,
|
fs: ctx.fs,
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: ctx.net,
|
net: ctx.net,
|
||||||
prt: ctx.prt,
|
prt: ctx.prt,
|
||||||
cfg: config,
|
cfg: config,
|
||||||
|
|
|
@ -47,6 +47,7 @@ pub(crate) fn a_nextcloud_config() -> NextcloudConfig {
|
||||||
pub(crate) fn a_full_context(fs: TempFileSystem, mock_net: MockNet) -> FullCtx {
|
pub(crate) fn a_full_context(fs: TempFileSystem, mock_net: MockNet) -> FullCtx {
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: a_printer(),
|
prt: a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -55,7 +55,12 @@ impl Execute for TrelloAttachmentCommand {
|
||||||
let trello_attachment_id = TrelloAttachmentId::new(attachment_id);
|
let trello_attachment_id = TrelloAttachmentId::new(attachment_id);
|
||||||
let file_name = ctx
|
let file_name = ctx
|
||||||
.trello_client()
|
.trello_client()
|
||||||
.save_attachment(&trello_card_id, &trello_attachment_id, file_name.as_ref())
|
.save_attachment(
|
||||||
|
&trello_card_id,
|
||||||
|
&trello_attachment_id,
|
||||||
|
file_name.as_ref(),
|
||||||
|
&ctx.fs,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
p!(ctx.prt, "Wrote: {}", file_name.display());
|
p!(ctx.prt, "Wrote: {}", file_name.display());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use color_eyre::eyre::Context;
|
use color_eyre::eyre::Context;
|
||||||
use kxio::net::{Net, ReqBuilder};
|
use kxio::{
|
||||||
|
fs::FileSystem,
|
||||||
|
net::{Net, ReqBuilder},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api_result::APIResult,
|
api_result::APIResult,
|
||||||
|
@ -72,13 +75,15 @@ impl<'ctx> TrelloClient<'ctx> {
|
||||||
card_id: &TrelloCardId,
|
card_id: &TrelloCardId,
|
||||||
attachment_id: &TrelloAttachmentId,
|
attachment_id: &TrelloAttachmentId,
|
||||||
file_name: Option<&PathBuf>,
|
file_name: Option<&PathBuf>,
|
||||||
|
fs: &FileSystem,
|
||||||
) -> color_eyre::Result<PathBuf> {
|
) -> color_eyre::Result<PathBuf> {
|
||||||
let attachment = self.card_attachment(card_id, attachment_id).await.result?;
|
let attachment = self.card_attachment(card_id, attachment_id).await.result?;
|
||||||
let url = attachment.url;
|
let url = attachment.url;
|
||||||
let file_name = file_name
|
let file_name = fs.base().join(
|
||||||
.cloned()
|
file_name
|
||||||
.unwrap_or_else(|| PathBuf::from((*attachment.file_name).clone()));
|
.cloned()
|
||||||
let file_name = self.ctx.fs.base().join(file_name);
|
.unwrap_or_else(|| PathBuf::from((*attachment.file_name).clone())),
|
||||||
|
);
|
||||||
let resp = with_exponential_backoff!(
|
let resp = with_exponential_backoff!(
|
||||||
&self.ctx,
|
&self.ctx,
|
||||||
self.ctx
|
self.ctx
|
||||||
|
@ -93,8 +98,13 @@ impl<'ctx> TrelloClient<'ctx> {
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
)
|
)
|
||||||
.context("downloading attachment")?;
|
.context("downloading attachment")?;
|
||||||
let file = self.ctx.fs.file(&file_name);
|
let file = fs.file(&file_name);
|
||||||
file.write(resp).context("writing to disk")?;
|
file.write(resp)
|
||||||
|
.map_err(|e| {
|
||||||
|
crate::e!(self.ctx.prt, "{}", e);
|
||||||
|
e
|
||||||
|
})
|
||||||
|
.with_context(|| f!("writing to disk: {} -> {}", file_name.display(), file))?;
|
||||||
Ok(file_name)
|
Ok(file_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -82,6 +82,7 @@ fn ctx_fs() -> (FullCtx, TempFileSystem) {
|
||||||
(
|
(
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -35,6 +35,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -35,6 +35,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -27,6 +27,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
|
@ -37,6 +37,7 @@ fn ctx() -> FullCtx {
|
||||||
|
|
||||||
FullCtx {
|
FullCtx {
|
||||||
fs: fs.as_real(),
|
fs: fs.as_real(),
|
||||||
|
temp_fs: fs.clone(),
|
||||||
net: mock_net.into(),
|
net: mock_net.into(),
|
||||||
prt: given::a_printer(),
|
prt: given::a_printer(),
|
||||||
cfg: AppConfig {
|
cfg: AppConfig {
|
||||||
|
|
Loading…
Reference in a new issue