pub mod caps;
pub mod extract;
pub mod replace;
pub mod set;
pub mod shorten;
pub mod trim;
pub use self::{
caps::Caps, extract::Extract, replace::Replace, set::Set, shorten::Shorten, trim::Trim,
};
use async_trait::async_trait;
use std::fmt::Debug;
use url::Url;
use super::{result::TransformResult, Transform};
use crate::{
action::transform::error::{TransformError, TransformErrorKind},
entry::Entry,
error::InvalidUrlError,
sink::message::Message,
utils::OptionExt,
};
pub trait TransformField: Debug + Send + Sync {
type Err: Into<TransformErrorKind>;
fn transform_field(&self, old_val: Option<&str>) -> Result<TransformResult<String>, Self::Err>;
}
#[derive(Debug)]
pub struct TransformFieldWrapper<T>
where
T: TransformField,
{
pub field: Field,
pub transformator: T,
}
#[async_trait]
impl<T> Transform for TransformFieldWrapper<T>
where
T: TransformField,
{
async fn transform(&self, mut entry: Entry) -> Result<Vec<Entry>, TransformError> {
let old_val = match self.field {
Field::Title => entry.msg.title.take(),
Field::Body => entry.msg.body.take(),
Field::Link => entry.msg.link.take().map(|u| u.to_string()),
Field::Id => entry.id.take().map(|id| id.0),
Field::ReplyTo => entry.reply_to.take().map(|id| id.0),
Field::RawContets => entry.raw_contents.take(),
};
let new_val = self
.transformator
.transform_field(old_val.as_deref())
.map_err(|kind| TransformError {
kind: kind.into(),
original_entry: entry.clone(),
})?;
let final_val = new_val.get(|| old_val);
let new_entry = match self.field {
Field::Title => Entry {
msg: Message {
title: final_val,
..entry.msg
},
..entry
},
Field::Body => Entry {
msg: Message {
body: final_val,
..entry.msg
},
..entry
},
Field::Link => {
let link = final_val.try_map(|s| {
Url::try_from(s.as_str()).map_err(|e| TransformError {
kind: TransformErrorKind::FieldLinkTransformInvalidUrl(InvalidUrlError(
e, s,
)),
original_entry: entry.clone(),
})
})?;
Entry {
msg: Message { link, ..entry.msg },
..entry
}
}
Field::Id => Entry {
id: final_val.map(Into::into),
..entry
},
Field::ReplyTo => Entry {
reply_to: final_val.map(Into::into),
..entry
},
Field::RawContets => Entry {
raw_contents: final_val,
..entry
},
};
Ok(vec![new_entry])
}
}
#[derive(Clone, Copy, Debug)]
pub enum Field {
Title,
Body,
Link,
Id,
ReplyTo,
RawContets,
}