use std::{collections::HashMap, str::FromStr};
use serde::{Deserialize, Serialize};
use serde_json::json;
use strum_macros::EnumString;
use crate::{
card::{
components::{
content_components::{plain_text::PlainText, title::FeishuCardTitle},
CardElement,
},
text::CustomTextSize,
},
service::im::v1::message::SendMessageTrait,
};
pub mod color;
pub mod components;
pub mod href;
pub mod icon;
pub mod interactions;
pub mod text;
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct FeishuCard {
#[serde(skip_serializing_if = "Option::is_none")]
pub config: Option<FeishuCardConfig>,
pub i18n_header: HashMap<FeishuCardLanguage, FeishuCardTitle>,
pub i18n_elements: HashMap<FeishuCardLanguage, Vec<CardElement>>,
}
impl SendMessageTrait for FeishuCard {
fn msg_type(&self) -> String {
"interactive".to_string()
}
fn content(&self) -> String {
json!(self).to_string()
}
}
impl FeishuCard {
pub fn new() -> Self {
let lng = FeishuCardLanguage::ZhCN;
let mut header = HashMap::new();
header.insert(lng, FeishuCardTitle::default());
let mut elements = HashMap::new();
elements.insert(lng, vec![]);
Self {
config: None,
i18n_header: header,
i18n_elements: elements,
}
}
pub fn config(mut self, config: FeishuCardConfig) -> Self {
self.config = Some(config);
self
}
pub fn header(mut self, lng: &str, header: FeishuCardTitle) -> Self {
let language: FeishuCardLanguage = lng.parse().expect("unknown language");
let origin_header = self.i18n_header.entry(language).or_default();
*origin_header = header;
self
}
pub fn elements(mut self, lng: &str, elements: Vec<CardElement>) -> Self {
let language: FeishuCardLanguage = lng.parse().expect("unknown language");
let self_elements = self.i18n_elements.entry(language).or_default();
self_elements.extend(elements);
self
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct FeishuCardConfig {
#[serde(skip_serializing_if = "Option::is_none")]
enable_forward: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
update_multi: Option<bool>,
width_mode: Option<FeishuCardWidthMode>,
#[serde(skip_serializing_if = "Option::is_none")]
use_custom_translation: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
enable_forward_interaction: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub style: Option<FeishuCardStyle>,
}
impl FeishuCardConfig {
pub fn new() -> Self {
Self::default()
}
pub fn enable_forward(mut self, enable_forward: bool) -> Self {
self.enable_forward = Some(enable_forward);
self
}
pub fn update_multi(mut self, update_multi: bool) -> Self {
self.update_multi = Some(update_multi);
self
}
pub fn width_mode(mut self, width_mode: FeishuCardWidthMode) -> Self {
self.width_mode = Some(width_mode);
self
}
pub fn use_custom_translation(mut self, use_custom_translation: bool) -> Self {
self.use_custom_translation = Some(use_custom_translation);
self
}
pub fn enable_forward_interaction(mut self, enable_forward_interaction: bool) -> Self {
self.enable_forward_interaction = Some(enable_forward_interaction);
self
}
pub fn style(mut self, style: FeishuCardStyle) -> Self {
self.style = Some(style);
self
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum FeishuCardWidthMode {
#[default]
Default,
Fill,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FeishuCardStyle {
#[serde(skip_serializing_if = "Option::is_none")]
text_size: Option<HashMap<String, CustomTextSize>>,
#[serde(skip_serializing_if = "Option::is_none")]
color: Option<HashMap<String, String>>,
}
#[derive(Debug, Serialize, Deserialize, Default, Eq, PartialEq, Hash, Clone, Copy)]
pub enum FeishuCardLanguage {
#[serde(rename = "zh_cn")]
#[default]
ZhCN,
#[serde(rename = "en_us")]
EnUS,
#[serde(rename = "ja_jp")]
JaJP,
#[serde(rename = "zh_hk")]
ZhHK,
#[serde(rename = "zh_tw")]
ZhTW,
}
impl FromStr for FeishuCardLanguage {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"zh_cn" => Ok(FeishuCardLanguage::ZhCN),
"en_us" => Ok(FeishuCardLanguage::EnUS),
"ja_jp" => Ok(FeishuCardLanguage::JaJP),
"zh_hk" => Ok(FeishuCardLanguage::ZhHK),
"zh_tw" => Ok(FeishuCardLanguage::ZhTW),
_ => Err(format!("unknown language: {}", s)),
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TextTag {
tag: String,
text: Option<PlainText>,
color: Option<String>,
}
impl Default for TextTag {
fn default() -> Self {
TextTag {
tag: "text_tag".to_string(),
text: None,
color: None,
}
}
}
impl TextTag {
pub fn new() -> Self {
Self::default()
}
pub fn text(mut self, text: PlainText) -> Self {
self.text = Some(text);
self
}
pub fn color(mut self, color: &str) -> Self {
self.color = Some(color.to_string());
self
}
}
#[derive(Debug, Serialize, Deserialize, Default, EnumString)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
pub enum FeishuCardHeaderTemplate {
Blue,
Wathet,
Turquoise,
Green,
Yellow,
Orange,
Red,
Carmine,
Violet,
Purple,
Indigo,
Grey,
#[default]
Default,
}
#[derive(Debug, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum MessageCardColor {
Neutral,
#[default]
Blue,
Turquoise,
Lime,
Orange,
Violet,
Indigo,
Wathet,
Green,
Yellow,
Red,
Purple,
Carmine,
}