1use minreq::get;
2use std::fs;
3use std::fs::File;
4use std::io::prelude::*;
5use std::io::BufReader;
6use std::path::Path;
7
8use crate::constants::GOOGLE_TTS_MAX_CHARS;
9use crate::languages::Languages;
10use crate::url::core::Core;
11
12#[derive(Debug)]
13pub struct GTTSClient {
14 pub volume: f32,
18 pub language: Languages,
22 pub tld: &'static str,
26}
27pub enum Speed {
28 Normal,
29 Slow,
30}
31impl GTTSClient {
32 pub fn default() -> Self {
34 GTTSClient {
35 volume: 1.0,
36 language: Languages::English,
37 tld: "com",
38 }
39 }
40 pub fn new(volume: f32, language: Languages, tld: &'static str) -> Self {
42 GTTSClient {
43 volume,
44 language,
45 tld,
46 }
47 }
48 pub fn save_to_file(&self, text: &str, filename: &str) -> Result<(), String> {
49 let len = text.len();
50 if len > GOOGLE_TTS_MAX_CHARS {
51 return Err(format!(
52 "The text is too long. Max length is {}",
53 GOOGLE_TTS_MAX_CHARS
54 ));
55 }
56 let language = Languages::as_code(self.language.clone());
57 let text = Core::fragmenter(text)?;
58 let rep = get(format!("https://translate.google.{}/translate_tts?ie=UTF-8&q={}&tl={}&total=1&idx=0&textlen={}&tl={}&client=tw-ob", self.tld, text.encoded, language, len, language))
59 .send()
60 .map_err(|e| format!("{}", e))?;
61 let mut file = File::create(filename).unwrap();
62 let bytes = rep.as_bytes();
63 if !bytes.is_empty() && file.write_all(bytes).is_ok() {
64 return Ok(());
65 }
66
67 Err("Something went wrong".to_string())
68 }
69 fn play_mp3(&self, mp3: &str) {
70 let (_stream, handle) = rodio::OutputStream::try_default().unwrap();
71 let sink = rodio::Sink::try_new(&handle).unwrap();
72 sink.set_volume(self.volume);
73 let file = std::fs::File::open(mp3).unwrap();
74 sink.append(rodio::Decoder::new(BufReader::new(file)).unwrap());
75 sink.sleep_until_end();
76 }
77 pub fn speak(&self, input: &str) -> Result<(), String> {
79 self.save_to_file(input, "audio.mp3")?;
80 self.play_mp3("audio.mp3");
81 if Path::new("./audio.mp3").exists() {
82 fs::remove_file("./audio.mp3").unwrap();
83 }
84 Ok(())
85 }
86 pub fn display_and_speak(&self, input: &str) {
88 self.speak(input).unwrap();
89 println!("{}", input);
90 }
91 pub fn test(&self) {
93 self.display_and_speak("Hello!");
94 }
95}
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_1() {
102 let narrator = GTTSClient::default();
103 narrator.test();
104 }
105}