1pub(crate) mod audio;
2pub(crate) mod chat;
3pub(crate) mod completions;
4pub(crate) mod edits;
5pub(crate) mod embeddings;
6pub(crate) mod images;
7pub(crate) mod models;
8
9use crate::error::ChatGptError;
10use reqwest::multipart::{Form, Part};
11use serde::Deserialize;
12use serde_json::{from_value, json, Map, Value};
13use std::io::Read;
14use std::path::Path;
15
16pub trait ChatGptRequest {
17 fn from_value(value: Value) -> Result<Self, ChatGptError>
18 where
19 Self: Sized;
20 fn to_value(&self) -> Value;
21}
22
23pub trait ChatGptResponse {
24 fn to_value(&self) -> &Value;
25}
26
27pub(crate) fn convert_from_value<T>(value: Value) -> Result<T, ChatGptError>
28where
29 T: for<'de> Deserialize<'de>,
30{
31 let request = from_value::<T>(value.clone());
32 match request {
33 Ok(request) => Ok(request),
34 Err(e) => Err(ChatGptError::JsonParse(json!({
35 "value": value,
36 "error": e.to_string()
37 }))),
38 }
39}
40
41pub(crate) fn convert_form(value: Value, file_keys: Vec<String>) -> Form {
42 let mut form = Form::new();
43 if !value.is_object() {
44 return form;
45 }
46 let data = value.as_object().unwrap().clone();
47 for (key, value) in data {
48 if !(value.is_string() || value.is_number()) {
49 continue;
50 }
51
52 let mut new_value = "".to_string();
53
54 if value.as_str().is_some() {
55 new_value = value.as_str().unwrap().to_string();
56 }
57 if value.as_u64().is_some() {
58 new_value = value.as_u64().unwrap().to_string();
59 }
60 if value.as_i64().is_some() {
61 new_value = value.as_i64().unwrap().to_string();
62 }
63 if value.as_f64().is_some() {
64 new_value = value.as_f64().unwrap().to_string();
65 }
66
67 if file_keys.contains(&key) {
68 let file_path = new_value.to_string();
69 let path = Path::new(&file_path);
70 if !path.exists() {
71 continue;
72 }
73 let mut file = std::fs::File::open(file_path.as_str()).unwrap();
74 let mut byte = vec![];
75 file.read_to_end(&mut byte).unwrap();
76 let file_name = path.file_name().unwrap().to_str().unwrap().to_string();
77 let mut mine = "".to_string();
78 if file_name.ends_with(".mp3") {
79 mine = "audio/mpeg".to_string();
80 } else if file_name.ends_with(".png") {
81 mine = "image/png".to_string();
82 }
83 let part = Part::bytes(byte)
84 .file_name(file_name)
85 .mime_str(mine.as_str())
86 .unwrap();
87 form = form.part("file", part);
89 } else {
90 form = form.text(key.clone(), new_value);
91 }
92 }
93 form
94}
95
96pub(crate) fn trim_value(value: Value) -> Option<Value> {
97 match value {
98 Value::Null => None,
99 Value::Bool(v) => Some(Value::Bool(v)),
100 Value::Number(v) => Some(Value::Number(v)),
101 Value::String(v) => Some(Value::String(v)),
102 Value::Array(v) => {
103 let mut rows = vec![];
104 for row in v {
105 if let Some(row) = trim_value(row) {
106 rows.push(row);
107 }
108 }
109 Some(Value::Array(rows))
110 }
111 Value::Object(v) => {
112 let mut hash = Map::new();
113 for (key, value) in v {
114 if let Some(value) = trim_value(value) {
115 hash.insert(key, value);
116 }
117 }
118 if hash.is_empty() {
119 None
120 } else {
121 Some(Value::Object(hash))
122 }
123 }
124 }
125}