rust_chatgpt/v1/
mod.rs

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            // let part = Part::bytes(byte).file_name(file_name).mime_str("audio/mpeg").unwrap();
88            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}