papago/
api.rs

1pub use self::model::Lang;
2
3pub use self::model::PapagoReq;
4
5use crate::config::NaverAuth;
6
7mod model;
8
9/// NMT_URL uses Neural Net Machine Translation
10pub const NMT_URL: &'static str = "https://openapi.naver.com/v1/papago/n2mt";
11/// SMT_URL uses Statistical Model
12pub const SMT_URL: &'static str = "https://openapi.naver.com/v1/language/translate";
13
14/// Error Type
15#[derive(PartialEq)]
16pub enum Error {
17    WrongPayload,
18    ReqFail,
19    RespParseFail,
20    PapagoError(String),
21}
22
23impl std::fmt::Debug for Error {
24    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25        match self {
26            Error::WrongPayload => write!(f, "Request payload is not correct"),
27            Error::ReqFail => write!(
28                f,
29                "Request has failed. Maybe check your internet connection."
30            ),
31            Error::RespParseFail => write!(
32                f,
33                "Response was not something expected. Please report if it's a bug"
34            ),
35            Error::PapagoError(msg) => write!(f, "{}", msg),
36        }
37    }
38}
39
40/// Returns Translation Result
41///
42/// # Arguments
43///
44/// * `url` - Use `SMT_URL` or `NMT_URL`
45/// * `auth` - Naver ClientId and ClientSecret
46/// * `payload` - Payload
47///
48/// # Example
49///
50/// ```rust
51/// # use papago::api::*;
52/// # use papago::config;
53/// let auth = config::get_auth_from_env().unwrap();
54/// let payload = PapagoReq {
55///     source: Lang::En,
56///     target: Lang::Ko,
57///     text: "HELLO WORLD".to_owned(),
58/// };
59/// let resp = send_request(NMT_URL, &auth, payload).unwrap();
60/// assert_eq!(resp, "안녕 세계".to_owned());
61/// ```
62pub fn send_request(
63    url: &'static str,
64    auth: &NaverAuth,
65    payload: model::PapagoReq,
66) -> Result<String, Error> {
67    let body = serde_urlencoded::to_string(&payload).or_else(|_| Err(Error::WrongPayload))?;
68
69    let client = reqwest::Client::new();
70    let mut resp = client
71        .post(url)
72        .header("X-Naver-Client-Id", auth.client_id.clone())
73        .header("X-Naver-Client-Secret", auth.client_secret.clone())
74        .header("Content-Type", "application/x-www-form-urlencoded")
75        .body(body)
76        .send()
77        .or(Err(Error::ReqFail))?;
78
79    let response: model::PapagoResponse = resp.json().or(Err(Error::RespParseFail))?;
80
81    match response {
82        model::PapagoResponse::Success { message } => Ok(message.result.translated_text),
83        model::PapagoResponse::Fail {
84            error_message,
85            error_code: _error_code,
86        } => Err(Error::PapagoError(error_message)),
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93    use crate::config;
94
95    #[test]
96    #[allow(non_snake_case)]
97    fn test_send_NMT_request() {
98        let auth = config::get_auth_from_env().unwrap();
99        let payload = model::PapagoReq {
100            source: model::Lang::En,
101            target: model::Lang::Ko,
102            text: "HELLO WORLD".to_owned(),
103        };
104        let result = send_request(NMT_URL, &auth, payload);
105        assert_eq!(result.unwrap(), "안녕 세계".to_owned());
106    }
107
108    #[test]
109    #[allow(non_snake_case)]
110    fn test_wrong_NMT_request__same_source_target() {
111        let auth = config::get_auth_from_env().unwrap();
112        let payload = model::PapagoReq {
113            source: model::Lang::En,
114            target: model::Lang::En,
115            text: "HELLO WORLD".to_owned(),
116        };
117        let result = send_request(NMT_URL, &auth, payload);
118        assert_eq!(
119            result.unwrap_err(),
120            Error::PapagoError(
121                "source and target must be different (source와 target이 동일합니다.)"
122                    .to_owned()
123            )
124        );
125    }
126
127    #[test]
128    #[allow(non_snake_case)]
129    fn test_wrong_NMT_request__wrong_lang_combo() {
130        let auth = config::get_auth_from_env().unwrap();
131        let payload = model::PapagoReq {
132            source: model::Lang::Vi,
133            target: model::Lang::Es,
134            text: "HELLO WORLD".to_owned(),
135        };
136        let result = send_request(NMT_URL, &auth, payload);
137        assert_eq!(
138            result.unwrap_err(),
139            Error::PapagoError(
140"There is no source-to-target translator (source->target 번역기가 없습니다.)"
141                    .to_owned()
142            )
143        );
144    }
145
146    #[test]
147    #[allow(non_snake_case)]
148    fn test_send_SMT_request() {
149        let auth = config::get_auth_from_env().unwrap();
150        let payload = model::PapagoReq {
151            source: model::Lang::En,
152            target: model::Lang::Ko,
153            text: "HELLO WORLD".to_owned(),
154        };
155        let result = send_request(SMT_URL, &auth, payload);
156        assert_eq!(result.unwrap(), "안녕 세계".to_owned());
157    }
158}