1use crate::card::replier::{AICardReplier, AICardStatus, CardReplier};
4
5const MARKDOWN_CARD_TEMPLATE_ID: &str = "589420e2-c1e2-46ef-a5ed-b8728e654da9.schema";
6const MARKDOWN_BUTTON_CARD_TEMPLATE_ID: &str = "1366a1eb-bc54-4859-ac88-517c56a9acb1.schema";
7const AI_MARKDOWN_CARD_TEMPLATE_ID: &str = "382e4302-551d-4880-bf29-a30acfab2e71.schema";
8const RPA_PLUGIN_CARD_TEMPLATE_ID: &str = "7f538f6d-ebb7-4533-a9ac-61a32da094cf.schema";
9
10pub struct MarkdownCardInstance {
12 replier: CardReplier,
13 pub card_instance_id: Option<String>,
15 title: Option<String>,
16 logo: Option<String>,
17}
18
19impl MarkdownCardInstance {
20 pub fn new(replier: CardReplier) -> Self {
22 Self {
23 replier,
24 card_instance_id: None,
25 title: None,
26 logo: None,
27 }
28 }
29
30 pub fn set_title_and_logo(&mut self, title: &str, logo: &str) {
32 self.title = Some(title.to_owned());
33 self.logo = Some(logo.to_owned());
34 }
35
36 fn get_card_data(&self, markdown: &str) -> serde_json::Value {
37 let mut data = serde_json::json!({"markdown": markdown});
38 if let Some(ref t) = self.title {
39 if !t.is_empty() {
40 data["title"] = serde_json::json!(t);
41 }
42 }
43 if let Some(ref l) = self.logo {
44 if !l.is_empty() {
45 data["logo"] = serde_json::json!(l);
46 }
47 }
48 data
49 }
50
51 pub async fn reply(
53 &mut self,
54 markdown: &str,
55 at_sender: bool,
56 at_all: bool,
57 recipients: Option<&[String]>,
58 support_forward: bool,
59 ) -> crate::Result<()> {
60 let card_data = self.get_card_data(markdown);
61 self.card_instance_id = Some(
62 self.replier
63 .create_and_send_card(
64 MARKDOWN_CARD_TEMPLATE_ID,
65 &card_data,
66 "STREAM",
67 "",
68 at_sender,
69 at_all,
70 recipients,
71 support_forward,
72 )
73 .await?,
74 );
75 Ok(())
76 }
77
78 pub async fn update(&self, markdown: &str) -> crate::Result<()> {
80 let id = self
81 .card_instance_id
82 .as_deref()
83 .ok_or_else(|| crate::Error::Card("card not sent yet".to_owned()))?;
84 self.replier
85 .put_card_data(id, &self.get_card_data(markdown), None)
86 .await
87 }
88}
89
90pub struct MarkdownButtonCardInstance {
92 replier: CardReplier,
93 pub card_instance_id: Option<String>,
95 title: Option<String>,
96 logo: Option<String>,
97 button_list: Vec<serde_json::Value>,
98}
99
100impl MarkdownButtonCardInstance {
101 pub fn new(replier: CardReplier) -> Self {
103 Self {
104 replier,
105 card_instance_id: None,
106 title: None,
107 logo: None,
108 button_list: Vec::new(),
109 }
110 }
111
112 pub fn set_title_and_logo(&mut self, title: &str, logo: &str) {
114 self.title = Some(title.to_owned());
115 self.logo = Some(logo.to_owned());
116 }
117
118 fn get_card_data(&self, markdown: &str, tips: &str) -> serde_json::Value {
119 let mut data = serde_json::json!({"markdown": markdown, "tips": tips});
120 if let Some(ref t) = self.title {
121 if !t.is_empty() {
122 data["title"] = serde_json::json!(t);
123 }
124 }
125 if let Some(ref l) = self.logo {
126 if !l.is_empty() {
127 data["logo"] = serde_json::json!(l);
128 }
129 }
130 if !self.button_list.is_empty() {
131 data["sys_full_json_obj"] = serde_json::Value::String(
132 serde_json::to_string(&serde_json::json!({"msgButtons": self.button_list}))
133 .unwrap_or_default(),
134 );
135 }
136 data
137 }
138
139 pub async fn reply(
141 &mut self,
142 markdown: &str,
143 button_list: Vec<serde_json::Value>,
144 tips: &str,
145 recipients: Option<&[String]>,
146 support_forward: bool,
147 ) -> crate::Result<()> {
148 self.button_list = button_list;
149 let card_data = self.get_card_data(markdown, tips);
150 self.card_instance_id = Some(
151 self.replier
152 .create_and_send_card(
153 MARKDOWN_BUTTON_CARD_TEMPLATE_ID,
154 &card_data,
155 "STREAM",
156 "",
157 false,
158 false,
159 recipients,
160 support_forward,
161 )
162 .await?,
163 );
164 Ok(())
165 }
166
167 pub async fn update(
169 &mut self,
170 markdown: &str,
171 button_list: Vec<serde_json::Value>,
172 tips: &str,
173 ) -> crate::Result<()> {
174 let id = self
175 .card_instance_id
176 .as_deref()
177 .ok_or_else(|| crate::Error::Card("card not sent yet".to_owned()))?;
178 self.button_list = button_list;
179 self.replier
180 .put_card_data(id, &self.get_card_data(markdown, tips), None)
181 .await
182 }
183}
184
185pub struct AIMarkdownCardInstance {
187 replier: AICardReplier,
188 pub card_instance_id: Option<String>,
190 title: Option<String>,
191 logo: Option<String>,
192 markdown: String,
193 static_markdown: String,
194 button_list: Option<Vec<serde_json::Value>>,
195 inputing_status: bool,
196 order: Vec<String>,
197}
198
199impl AIMarkdownCardInstance {
200 pub fn new(replier: AICardReplier) -> Self {
202 Self {
203 replier,
204 card_instance_id: None,
205 title: None,
206 logo: None,
207 markdown: String::new(),
208 static_markdown: String::new(),
209 button_list: None,
210 inputing_status: false,
211 order: vec![
212 "msgTitle".to_owned(),
213 "msgContent".to_owned(),
214 "staticMsgContent".to_owned(),
215 "msgTextList".to_owned(),
216 "msgImages".to_owned(),
217 "msgSlider".to_owned(),
218 "msgButtons".to_owned(),
219 ],
220 }
221 }
222
223 pub fn set_title_and_logo(&mut self, title: &str, logo: &str) {
225 self.title = Some(title.to_owned());
226 self.logo = Some(logo.to_owned());
227 }
228
229 pub fn set_order(&mut self, order: Vec<String>) {
231 self.order = order;
232 }
233
234 pub fn get_card_data(&self, flow_status: Option<AICardStatus>) -> serde_json::Value {
236 let mut data = serde_json::json!({
237 "msgContent": self.markdown,
238 "staticMsgContent": self.static_markdown,
239 });
240 if let Some(status) = flow_status {
241 data["flowStatus"] = serde_json::json!(status as u8);
242 }
243 if let Some(ref t) = self.title {
244 if !t.is_empty() {
245 data["msgTitle"] = serde_json::json!(t);
246 }
247 }
248 if let Some(ref l) = self.logo {
249 if !l.is_empty() {
250 data["logo"] = serde_json::json!(l);
251 }
252 }
253
254 let mut sys_full = serde_json::json!({"order": self.order});
255 if let Some(ref buttons) = self.button_list {
256 if !buttons.is_empty() {
257 sys_full["msgButtons"] = serde_json::json!(buttons);
258 }
259 }
260 if let Some(ref hosting) = self.replier.inner().incoming_message.hosting_context {
261 sys_full["source"] =
262 serde_json::json!({"text": format!("由{}的数字助理回答", hosting.nick)});
263 }
264 data["sys_full_json_obj"] =
265 serde_json::Value::String(serde_json::to_string(&sys_full).unwrap_or_default());
266 data
267 }
268
269 pub async fn ai_start(
271 &mut self,
272 recipients: Option<&[String]>,
273 support_forward: bool,
274 ) -> crate::Result<()> {
275 if self.card_instance_id.is_some() {
276 return Ok(());
277 }
278 self.card_instance_id = Some(
279 self.replier
280 .start(
281 AI_MARKDOWN_CARD_TEMPLATE_ID,
282 &serde_json::json!({}),
283 recipients,
284 support_forward,
285 )
286 .await?,
287 );
288 self.inputing_status = false;
289 Ok(())
290 }
291
292 pub async fn ai_streaming(&mut self, markdown: &str, append: bool) -> crate::Result<()> {
294 let id = self
295 .card_instance_id
296 .as_deref()
297 .ok_or_else(|| crate::Error::Card("card not started yet".to_owned()))?
298 .to_owned();
299 if !self.inputing_status {
300 let card_data = self.get_card_data(Some(AICardStatus::Inputing));
301 self.replier
302 .inner()
303 .put_card_data(&id, &card_data, None)
304 .await?;
305 self.inputing_status = true;
306 }
307 if append {
308 self.markdown.push_str(markdown);
309 } else {
310 self.markdown = markdown.to_owned();
311 }
312 self.replier
313 .streaming(&id, "msgContent", &self.markdown, false, false, false)
314 .await
315 }
316
317 pub async fn ai_finish(
319 &mut self,
320 markdown: Option<&str>,
321 button_list: Option<Vec<serde_json::Value>>,
322 _tips: &str,
323 ) -> crate::Result<()> {
324 let id = self
325 .card_instance_id
326 .as_deref()
327 .ok_or_else(|| crate::Error::Card("card not started yet".to_owned()))?
328 .to_owned();
329 if let Some(md) = markdown {
330 self.markdown = md.to_owned();
331 }
332 if let Some(buttons) = button_list {
333 self.button_list = Some(buttons);
334 }
335 self.replier.finish(&id, &self.get_card_data(None)).await
336 }
337
338 pub async fn update(
340 &mut self,
341 static_markdown: Option<&str>,
342 button_list: Option<Vec<serde_json::Value>>,
343 _tips: &str,
344 ) -> crate::Result<()> {
345 let id = self
346 .card_instance_id
347 .as_deref()
348 .ok_or_else(|| crate::Error::Card("card not started yet".to_owned()))?
349 .to_owned();
350 if let Some(buttons) = button_list {
351 self.button_list = Some(buttons);
352 }
353 if let Some(sm) = static_markdown {
354 self.static_markdown = sm.to_owned();
355 }
356 self.replier.finish(&id, &self.get_card_data(None)).await
357 }
358
359 pub async fn ai_fail(&mut self) -> crate::Result<()> {
361 let id = self
362 .card_instance_id
363 .as_deref()
364 .ok_or_else(|| crate::Error::Card("card not started yet".to_owned()))?
365 .to_owned();
366 let mut card_data = serde_json::json!({});
367 if let Some(ref t) = self.title {
368 if !t.is_empty() {
369 card_data["msgTitle"] = serde_json::json!(t);
370 }
371 }
372 if let Some(ref l) = self.logo {
373 if !l.is_empty() {
374 card_data["logo"] = serde_json::json!(l);
375 }
376 }
377 self.replier.fail(&id, &card_data).await
378 }
379}
380
381pub struct CarouselCardInstance {
383 replier: AICardReplier,
384 pub card_instance_id: Option<String>,
386 title: Option<String>,
387 logo: Option<String>,
388}
389
390impl CarouselCardInstance {
391 pub fn new(replier: AICardReplier) -> Self {
393 Self {
394 replier,
395 card_instance_id: None,
396 title: None,
397 logo: None,
398 }
399 }
400
401 pub fn set_title_and_logo(&mut self, title: &str, logo: &str) {
403 self.title = Some(title.to_owned());
404 self.logo = Some(logo.to_owned());
405 }
406
407 pub async fn ai_start(&mut self) -> crate::Result<()> {
409 self.card_instance_id = Some(
410 self.replier
411 .start(
412 AI_MARKDOWN_CARD_TEMPLATE_ID,
413 &serde_json::json!({}),
414 None,
415 true,
416 )
417 .await?,
418 );
419 Ok(())
420 }
421
422 pub async fn reply(
424 &mut self,
425 markdown: &str,
426 image_slider_list: &[(String, String)],
427 button_text: &str,
428 recipients: Option<&[String]>,
429 support_forward: bool,
430 ) -> crate::Result<()> {
431 let slider: Vec<serde_json::Value> = image_slider_list
432 .iter()
433 .map(|(t, i)| serde_json::json!({"title": t, "image": i}))
434 .collect();
435 let sys_full = serde_json::json!({
436 "order": ["msgTitle", "staticMsgContent", "msgSlider", "msgImages", "msgTextList", "msgButtons"],
437 "msgSlider": slider,
438 "msgButtons": [{"text": button_text, "color": "blue", "id": "image_slider_select_button", "request": true}]
439 });
440 let mut card_data = serde_json::json!({"staticMsgContent": markdown, "sys_full_json_obj": serde_json::to_string(&sys_full).unwrap_or_default()});
441 if let Some(ref t) = self.title {
442 if !t.is_empty() {
443 card_data["msgTitle"] = serde_json::json!(t);
444 }
445 }
446 if let Some(ref l) = self.logo {
447 if !l.is_empty() {
448 card_data["logo"] = serde_json::json!(l);
449 }
450 }
451
452 self.card_instance_id = Some(
453 self.replier
454 .inner()
455 .create_and_send_card(
456 AI_MARKDOWN_CARD_TEMPLATE_ID,
457 &serde_json::json!({"flowStatus": AICardStatus::Processing as u8}),
458 "STREAM",
459 "",
460 false,
461 false,
462 recipients,
463 support_forward,
464 )
465 .await?,
466 );
467 let id = self.card_instance_id.as_deref().unwrap_or_default();
468 self.replier.finish(id, &card_data).await
469 }
470}
471
472pub struct RPAPluginCardInstance {
474 replier: AICardReplier,
475 pub card_instance_id: Option<String>,
477 goal: String,
478 corp_id: String,
479}
480
481impl RPAPluginCardInstance {
482 pub fn new(replier: AICardReplier) -> Self {
484 Self {
485 replier,
486 card_instance_id: None,
487 goal: String::new(),
488 corp_id: String::new(),
489 }
490 }
491
492 pub fn set_goal(&mut self, goal: &str) {
494 self.goal = goal.to_owned();
495 }
496
497 pub fn set_corp_id(&mut self, corp_id: &str) {
499 self.corp_id = corp_id.to_owned();
500 }
501
502 #[allow(clippy::too_many_arguments)]
504 pub async fn reply(
505 &mut self,
506 plugin_id: &str,
507 plugin_version: &str,
508 plugin_name: &str,
509 ability_name: &str,
510 plugin_args: &serde_json::Value,
511 recipients: Option<&[String]>,
512 support_forward: bool,
513 ) -> crate::Result<()> {
514 let plan = serde_json::json!({
515 "corpId": self.corp_id, "goal": self.goal,
516 "plan": format!("(function(){{dd.callPlugin({{'pluginName':'{}','abilityName':'{}','args':{} }});}})())", plugin_name, ability_name, serde_json::to_string(plugin_args).unwrap_or_default()),
517 "planType": "jsCode",
518 "pluginInstances": [{"id": format!("AGI-EXTENSION-{}", plugin_id), "version": plugin_version}]
519 });
520 let card_data = serde_json::json!({"goal": self.goal, "processFlag": "true", "plan": serde_json::to_string(&plan).unwrap_or_default()});
521
522 self.card_instance_id = Some(
523 self.replier
524 .inner()
525 .create_and_send_card(
526 RPA_PLUGIN_CARD_TEMPLATE_ID,
527 &serde_json::json!({"flowStatus": AICardStatus::Processing as u8}),
528 "STREAM",
529 "",
530 false,
531 false,
532 recipients,
533 support_forward,
534 )
535 .await?,
536 );
537 let id = self.card_instance_id.as_deref().unwrap_or_default();
538 self.replier.finish(id, &card_data).await
539 }
540}