1use std::error::Error;
2
3use crate::{CompareResponse, CreateCategoryFilterRequest, CreateCategoryFilterResponse, Fingerprint, GetTermsContextsRequest, GetTermsContextsResponse, GetTermsRequest, GetTermsResponse, GetTermsSimilarTermsRequest, LanguageResponse, PosType, Retina, TextEnvelope, TextSlice, TextSliceRequest};
4
5pub struct Cortical {
6 pub client: reqwest::Client,
7 pub base_url: String,
8}
9
10impl Cortical {
11 pub fn new() -> Cortical {
12 Cortical {
13 client: reqwest::Client::new(),
14 base_url: std::env::var("CORTICAL_API_URL").unwrap_or("https://languages.cortical.io".to_string()),
15 }
16 }
17
18 pub async fn get_retinas(&self) -> Result<Vec<Retina>, Box<dyn Error>> {
19 let response =
20 self.client
21 .get(format!("{}{}", &self.base_url, "/rest/retinas"))
22 .send()
23 .await?;
24
25 Ok(
26 response
27 .json()
28 .await?
29 )
30 }
31
32 pub async fn get_text_analysis(
33 &self,
34 text: &str,
35 retina_name: Option<&str>,
36 ) -> Result<Vec<Fingerprint>, Box<dyn Error>> {
37 let retina_name = retina_name.unwrap_or("en_general");
38
39 let response =
40 self.client
41 .post(format!("{}/rest/text?retina_name={}", &self.base_url, retina_name))
42 .header("Accept", "application/json")
43 .header("Referer", "")
44 .header("Content-Type", "application/json")
45 .body(text.to_string())
46 .send()
47 .await?;
48
49 Ok(
50 response
51 .json()
52 .await?
53 )
54 }
55
56 pub async fn get_text_keywords(
57 &self,
58 text: &str,
59 retina_name: Option<&str>,
60 ) -> Result<Vec<String>, Box<dyn Error>> {
61 let retina_name = retina_name.unwrap_or("en_general");
62
63 let response =
64 self.client
65 .post(format!("{}/rest/text/keywords?retina_name={}", &self.base_url, retina_name))
66 .header("Accept", "application/json")
67 .header("Referer", "")
68 .header("Content-Type", "text/plain;charset=UTF-8")
69 .body(text.to_string())
70 .send()
71 .await?;
72
73 Ok(
74 response
75 .json()
76 .await?
77 )
78 }
79
80 pub async fn get_text_slices(
81 &self,
82 text: &str,
83 params: Option<TextSliceRequest>,
84 ) -> Result<Vec<TextSlice>, Box<dyn Error>> {
85 let params = params.unwrap_or_default();
86
87 let response =
88 self.client
89 .post(
90 format!(
91 "{}/rest/text/slices?retina_name={}&start_index={}&max_results={}&get_fingerprint={}",
92 &self.base_url,
93 params.retina_name,
94 params.start_index,
95 params.max_results,
96 params.get_fingerprint
97 )
98 )
99 .header("Accept", "application/json")
100 .header("Referer", "")
101 .header("Content-Type", "application/json")
102 .body(text.to_string())
103 .send()
104 .await?;
105
106 Ok(
107 response
108 .json()
109 .await?
110 )
111 }
112
113 pub async fn get_text_detect_language(
114 &self,
115 text: &str,
116 ) -> Result<LanguageResponse, Box<dyn Error>> {
117 let response =
118 self.client
119 .post(format!("{}/rest/text/detect_language", &self.base_url))
120 .header("Accept", "application/json")
121 .header("Referer", "")
122 .header("Content-Type", "application/json")
123 .body(text.to_string())
124 .send()
125 .await?;
126
127 Ok(
128 response
129 .json()
130 .await?
131 )
132 }
133
134 pub async fn create_category_filter(
135 &self,
136 positive_examples: Vec<String>,
137 negative_examples: Vec<String>,
138 retina_name: Option<&str>,
139 ) -> Result<CreateCategoryFilterResponse, Box<dyn Error>> {
140 let retina_name = retina_name.unwrap_or("en_general");
141
142 let positive_examples = positive_examples
143 .into_iter()
144 .map(|text| TextEnvelope { text })
145 .collect();
146
147 let negative_examples = negative_examples
148 .into_iter()
149 .map(|text| TextEnvelope { text })
150 .collect();
151
152 let request = CreateCategoryFilterRequest {
153 category_name: None,
154 positive_examples,
155 negative_examples,
156 };
157
158 Ok(
159 self.client
160 .post(
161 format!(
162 "{}/rest/classify/create_category_filter?retina_name={}&filter_name={}",
163 &self.base_url,
164 retina_name,
165 "filter_name"
166 )
167 )
168 .header("Accept", "application/json")
169 .header("Referer", "")
170 .header("Content-Type", "application/json")
171 .body(serde_json::to_string(&request)?)
172 .send()
173 .await?
174 .json()
175 .await?
176 )
177 }
178
179 pub async fn get_compare(
180 &self,
181 (text1, text2): (&str, &str),
182 retina_name: Option<&str>,
183 ) -> Result<CompareResponse, Box<dyn Error>> {
184 let retina_name = retina_name.unwrap_or("en_general");
185
186 Ok(
187 self.client
188 .post(format!("{}/rest/compare?retina_name={}", &self.base_url, retina_name))
189 .header("Accept", "application/json")
190 .header("Referer", "")
191 .header("Content-Type", "application/json")
192 .body(
193 serde_json::to_string(
194 &vec![
195 TextEnvelope::new(text1),
196 TextEnvelope::new(text2),
197 ]
198 )?
199 )
200 .send()
201 .await?
202 .json()
203 .await?
204 )
205 }
206
207 pub async fn get_terms(
208 &self,
209 retina_name: Option<&str>,
210 term: Option<&str>,
211 get_fingerpint: Option<bool>,
212 start_index: Option<u32>,
213 max_results: Option<u32>,
214 ) -> Result<GetTermsResponse, Box<dyn Error>> {
215 let retina_name = retina_name.unwrap_or("en_general");
216
217 let query =
218 GetTermsRequest {
219 retina_name: retina_name.to_string(),
220 term: term.map(|term| term.to_string()),
221 start_index,
222 max_results,
223 get_fingerprint: get_fingerpint.unwrap_or(false),
224 };
225
226 let response =
227 self.client
228 .get(format!("{}/rest/terms", &self.base_url))
229 .header("Accept", "application/json")
230 .header("Referer", "")
231 .header("Content-Type", "application/json")
232 .query(&query)
233 .send()
234 .await?;
235
236 Ok(
237 response
238 .json()
239 .await?
240 )
241 }
242
243 pub async fn get_terms_contexts(
244 &self,
245 term: &str,
246 retina_name: Option<&str>,
247 get_fingerpint: Option<bool>,
248 start_index: Option<u32>,
249 max_results: Option<u32>,
250 ) -> Result<GetTermsContextsResponse, Box<dyn Error>> {
251 let retina_name = retina_name.unwrap_or("en_general");
252
253 let query =
254 GetTermsContextsRequest {
255 retina_name: retina_name.to_string(),
256 term: term.to_string(),
257 start_index,
258 max_results,
259 get_fingerprint: get_fingerpint.unwrap_or(false),
260 };
261
262 let response =
263 self.client
264 .get(format!("{}/rest/terms/contexts", &self.base_url))
265 .header("Accept", "application/json")
266 .header("Referer", "")
267 .header("Content-Type", "application/json")
268 .query(&query)
269 .send()
270 .await?;
271
272 Ok(
273 response
274 .json()
275 .await?
276 )
277 }
278
279 pub async fn get_terms_similar_terms(
280 &self,
281 term: &str,
282 retina_name: Option<&str>,
283 context_id: Option<&str>,
284 pos_type: Option<PosType>,
285 get_fingerpint: Option<bool>,
286 start_index: Option<u32>,
287 max_results: Option<u32>,
288 ) -> Result<GetTermsResponse, Box<dyn Error>> {
289 let retina_name = retina_name.unwrap_or("en_general");
290
291 let query =
292 GetTermsSimilarTermsRequest {
293 retina_name: retina_name.to_string(),
294 term: term.to_string(),
295 context_id: context_id.map(|c| c.to_string()),
296 pos_type,
297 start_index,
298 max_results,
299 get_fingerprint: get_fingerpint.unwrap_or(false),
300 };
301
302 let response =
303 self.client
304 .get(format!("{}/rest/terms/contexts", &self.base_url))
305 .header("Accept", "application/json")
306 .header("Referer", "")
307 .header("Content-Type", "application/json")
308 .query(&query)
309 .send()
310 .await?;
311
312 Ok(
313 response
314 .json()
315 .await?
316 )
317 }
318}