use reqwest::Client;
use serde::Deserialize;
use serde_json::json;
use synaptic_core::SynapticError;
use super::streaming::{StreamingCardOptions, StreamingCardWriter};
use crate::{api::cardkit::CardKitApi, api::message::MessageApi, auth::TokenCache, LarkConfig};
pub struct LarkBotClient {
pub(crate) app_id: String,
pub(crate) config: LarkConfig,
token_cache: TokenCache,
base_url: String,
client: Client,
msg_api: MessageApi,
cardkit_api: CardKitApi,
}
#[derive(Debug, Deserialize)]
pub struct BotInfo {
pub app_name: String,
pub avatar_url: String,
pub ip_white_list: Vec<String>,
pub open_id: String,
}
impl LarkBotClient {
pub fn new(config: LarkConfig) -> Self {
let app_id = config.app_id.clone();
let base_url = config.base_url.clone();
let msg_api = MessageApi::new(config.clone());
let cardkit_api = CardKitApi::new(config.clone());
Self {
app_id,
config: config.clone(),
token_cache: config.token_cache(),
base_url,
client: Client::new(),
msg_api,
cardkit_api,
}
}
pub fn app_id(&self) -> &str {
&self.app_id
}
pub async fn get_bot_info(&self) -> Result<BotInfo, SynapticError> {
let token = self.token_cache.get_token().await?;
let url = format!("{}/bot/v3/info", self.base_url);
let resp: serde_json::Value = self
.client
.get(&url)
.bearer_auth(token)
.send()
.await
.map_err(|e| SynapticError::Tool(format!("get_bot_info: {e}")))?
.json()
.await
.map_err(|e| SynapticError::Tool(format!("get_bot_info parse: {e}")))?;
if resp["code"].as_i64().unwrap_or(-1) != 0 {
return Err(SynapticError::Tool(format!(
"get_bot_info error: {}",
resp["msg"].as_str().unwrap_or("unknown")
)));
}
let bot = &resp["bot"];
Ok(BotInfo {
app_name: bot["app_name"].as_str().unwrap_or("").to_string(),
avatar_url: bot["avatar_url"].as_str().unwrap_or("").to_string(),
ip_white_list: bot["ip_white_list"]
.as_array()
.map(|a| {
a.iter()
.filter_map(|v| v.as_str().map(String::from))
.collect()
})
.unwrap_or_default(),
open_id: bot["open_id"].as_str().unwrap_or("").to_string(),
})
}
pub async fn send_text(
&self,
receive_id_type: &str,
receive_id: &str,
text: &str,
) -> Result<String, SynapticError> {
let content_json = json!({ "text": text }).to_string();
self.msg_api
.send(receive_id_type, receive_id, "text", &content_json)
.await
}
pub async fn reply_text(&self, message_id: &str, text: &str) -> Result<String, SynapticError> {
let content_json = json!({ "text": text }).to_string();
self.msg_api.reply(message_id, "text", &content_json).await
}
pub async fn create_card(
&self,
card_json: &serde_json::Value,
) -> Result<String, SynapticError> {
self.cardkit_api.create(card_json).await
}
pub async fn update_card(
&self,
card_id: &str,
sequence: i64,
card_json: &serde_json::Value,
) -> Result<(), SynapticError> {
self.cardkit_api.update(card_id, sequence, card_json).await
}
pub async fn stream_card_content(
&self,
card_id: &str,
element_id: &str,
content: &str,
sequence: i64,
) -> Result<(), SynapticError> {
self.cardkit_api
.stream_content(card_id, element_id, content, sequence)
.await
}
pub async fn send_card(
&self,
receive_id_type: &str,
receive_id: &str,
card_json: &serde_json::Value,
) -> Result<String, SynapticError> {
let content_json = card_json.to_string();
self.msg_api
.send(receive_id_type, receive_id, "interactive", &content_json)
.await
}
pub async fn reply_card(
&self,
message_id: &str,
card_json: &serde_json::Value,
) -> Result<String, SynapticError> {
let content_json = card_json.to_string();
self.msg_api
.reply(message_id, "interactive", &content_json)
.await
}
pub async fn streaming_send(
&self,
receive_id_type: &str,
receive_id: &str,
options: StreamingCardOptions,
) -> Result<StreamingCardWriter, SynapticError> {
StreamingCardWriter::send(self.config.clone(), receive_id_type, receive_id, options).await
}
pub async fn streaming_reply(
&self,
reply_to_message_id: &str,
options: StreamingCardOptions,
) -> Result<StreamingCardWriter, SynapticError> {
StreamingCardWriter::reply(self.config.clone(), reply_to_message_id, options).await
}
}