use std::fs;
use json::{array, JsonValue, object};
use lazy_static::lazy_static;
use crate::Connection;
use crate::mode::{OcrMode};
use std::sync::Mutex;
use std::collections::HashMap;
use br_crypto::encoding::urlencoding_encode;
use br_http::FormData;
use chrono::Local;
lazy_static! {
static ref ACCESS_TOKEN: Mutex<HashMap<String,JsonValue>> =Mutex::new(HashMap::new());
}
#[derive(Clone)]
pub struct Baidu {
pub appid: String,
pub secret: String,
pub access_token: String,
pub expires_in: i64,
}
impl Baidu {
pub fn new(connection: Connection) -> Self {
Self {
appid: connection.appid,
secret: connection.secret,
access_token: "".to_string(),
expires_in: 0,
}
}
pub fn get_access_token(&mut self) -> String {
let dt = Local::now();
let timestamp = dt.timestamp_millis();
if self.expires_in > timestamp {
return self.access_token.clone();
}
let url = format!("https://aip.baidubce.com/oauth/2.0/token?client_id={}&client_secret={}&grant_type=client_credentials", self.appid, self.secret);
let mut http = br_http::Http::new();
let http = http.post(url.as_str()).header("Accept", "application/json").form_urlencoded(object! {});
let res = http.json().unwrap();
if res["access_token"].is_empty() {
return self.access_token.clone();
}
self.access_token = res["access_token"].to_string();
self.expires_in = timestamp + res["expires_in"].as_i64().unwrap();
ACCESS_TOKEN.lock().unwrap().insert(self.appid.clone(), object! {
access_token: self.access_token.clone(),
expires_in:self.expires_in
});
self.access_token.clone()
}
}
impl OcrMode for Baidu {
fn ocr(&mut self, file_path: &str, file_b64: &str) -> JsonValue {
self.get_access_token();
let file_base64: String = if file_b64.is_empty() {
let file_data = fs::read(file_path).unwrap();
br_crypto::base64::encode_file(file_data)
} else {
file_b64.to_string()
};
let _image = urlencoding_encode(file_base64.as_str());
let url = format!("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token={}", self.access_token);
let mut http = br_http::Http::new();
let tt = vec![
FormData::File("image".to_string(), file_base64,"".to_string()),
FormData::Text("detect_direction".parse().unwrap(), "true".into(),"".to_string()),
FormData::Text("paragraph".parse().unwrap(), "false".into(),"".to_string()),
FormData::Text("probability".parse().unwrap(), "false".into(),"".to_string())
];
let http = http.post(url.as_str())
.header("Accept", "application/json")
.form_data(tt);
let res = http.json().unwrap();
if res["words_result"].is_empty() {
return array![];
}
let mut list = vec![];
for item in res["words_result"].members() {
list.push(item["words"].as_str().unwrap());
}
list.into()
}
fn translate(&mut self, text: &str) -> JsonValue {
self.get_access_token();
let url = format!("https://aip.baidubce.com/rpc/2.0/mt/texttrans/v1?access_token={}", self.access_token);
let mut http = br_http::Http::new();
let http = http.post(url.as_str()).header("Content-Type", "application/json;charset=utf-8").raw_json(object! {
"from": "auto",
"to": "zh",
"q": text
});
let res = http.json().unwrap();
if res["result"]["trans_result"].is_empty() {
return array![];
}
res["result"]["trans_result"].clone()
}
}