source: code/trunk/engines/google.go@ 72

Last change on this file since 72 was 40, checked in by manerakai, 21 months ago

Fixed bug

File size: 9.4 KB
Line 
1package engines
2
3import (
4 "bytes"
5 "fmt"
6 "io/ioutil"
7 "net/http"
8 "net/url"
9
10 "encoding/json"
11 "regexp"
12
13 "github.com/PuerkitoBio/goquery"
14)
15
16type GoogleTranslate struct{}
17
18func (_ *GoogleTranslate) DisplayName() string { return "Google Translate" }
19
20func (_ *GoogleTranslate) getLangs(type_ string) (Language, error) {
21 var langsType string
22 switch type_ {
23 case "source":
24 langsType = "sl"
25
26 case "target":
27 langsType = "tl"
28
29 default:
30 return nil, fmt.Errorf("Invalid language type: %s", langsType)
31 }
32
33 requestURL, _ := url.Parse("https://translate.google.com/m")
34
35 query := url.Values{}
36 query.Add("mui", langsType)
37 query.Add("hl", "en-US")
38 requestURL.RawQuery = query.Encode()
39
40 response, err := http.Get(requestURL.String())
41 if err != nil {
42 return nil, err
43 }
44
45 defer response.Body.Close()
46
47 doc, err := goquery.NewDocumentFromReader(response.Body)
48 if err != nil {
49 return nil, err
50 }
51
52 var langs Language = make(Language)
53
54 doc.Find(".language-item").Each(func(_ int, s *goquery.Selection) {
55 a := s.Find("a").First()
56
57 href, exists := a.Attr("href")
58 if !exists {
59 return
60 }
61
62 langURL, err := url.Parse(href)
63 if err != nil {
64 return
65 }
66
67 langCode := langURL.Query()[langsType][0]
68
69 langs[langCode] = a.Text()
70 })
71
72 return langs, nil
73}
74
75func (e *GoogleTranslate) SourceLanguages() (Language, error) {
76 return e.getLangs("source")
77}
78
79func (e *GoogleTranslate) TargetLanguages() (Language, error) {
80 return e.getLangs("target")
81}
82
83func (e *GoogleTranslate) Tts(text, lang string) (string, error) {
84 requestURL, _ := url.Parse("https://translate.google.com/translate_tts")
85
86 query := url.Values{}
87 query.Add("tl", lang)
88 query.Add("q", text)
89 query.Add("client", "tw-ob")
90 requestURL.RawQuery = query.Encode()
91
92 return requestURL.String(), nil
93}
94
95func (_ *GoogleTranslate) Translate(text string, from, to string) (TranslationResult, error) {
96 requestURL, _ := url.Parse("https://translate.google.com/m")
97
98 if from == "" {
99 from = "auto"
100 }
101
102 query := url.Values{}
103 query.Add("sl", from)
104 query.Add("tl", to)
105 query.Add("hl", to)
106 query.Add("q", text)
107 requestURL.RawQuery = query.Encode()
108
109 response, err := http.Get(requestURL.String())
110
111 if err != nil {
112 return TranslationResult{}, err
113 }
114
115 defer response.Body.Close()
116
117 doc, err := goquery.NewDocumentFromReader(response.Body)
118
119 translatedText := doc.Find(".result-container").Text()
120
121 if err != nil {
122 return TranslationResult{}, err
123 }
124
125 url_ := "https://translate.google.com/_/TranslateWebserverUi/data/batchexecute?rpcids=MkEWBc&rt=c"
126
127 reqJSON := []interface{}{
128 []interface{}{text, from, to, true},
129 []interface{}{nil},
130 }
131 reqJSONString, err := json.Marshal(reqJSON)
132 if err != nil {
133 fmt.Println("Error:", err)
134 return TranslationResult{}, nil
135 }
136
137 req := []interface{}{[]interface{}{[]interface{}{"MkEWBc", string(reqJSONString), nil, "generic"}}}
138
139 JSONString, _ := json.Marshal(req)
140
141 body := "f.req=" + url.QueryEscape(string(JSONString))
142
143 resp, err := http.Post(url_, "application/x-www-form-urlencoded;charset=utf-8", bytes.NewBuffer([]byte(body)))
144 if err != nil {
145 fmt.Println("Error:", err)
146 return TranslationResult{}, nil
147 }
148 defer resp.Body.Close()
149
150 bodyBytes, err := ioutil.ReadAll(resp.Body)
151 if err != nil {
152 fmt.Println("Error:", err)
153 return TranslationResult{}, nil
154 }
155 responseText := string(bodyBytes)
156 responseTextList := regexp.MustCompile(`\n\d+\n(.*)\n\d+\n`).FindStringSubmatch(responseText)
157 definitions := make(map[string][]map[string]interface{})
158 translations := make(map[string]map[string]map[string]interface{})
159 if len(responseTextList) > 0 {
160 responseText = responseTextList[1]
161 var raw []interface{}
162 err = json.Unmarshal([]byte(responseText), &raw)
163 if err != nil {
164 fmt.Println("Error:", err)
165 return TranslationResult{}, nil
166 }
167
168 if len(raw) > 0 && raw[0] != nil &&
169 len(raw[0].([]interface{})) > 2 && raw[0].([]interface{})[2] != nil {
170 data := raw[0].([]interface{})[2].(string)
171
172 var json_ []interface{}
173 err = json.Unmarshal([]byte(data), &json_)
174
175 if len(json_) > 3 && json_[3] != nil &&
176 len(json_[3].([]interface{})) > 1 && json_[3].([]interface{})[1] != nil &&
177 len(json_[3].([]interface{})[1].([]interface{})) > 0 && json_[3].([]interface{})[1].([]interface{})[0] != nil {
178 for x := 0; x < len(json_[3].([]interface{})[1].([]interface{})[0].([]interface{})); x++ {
179 if len(json_[3].([]interface{})[1].([]interface{})[0].([]interface{})[x].([]interface{})) > 0 {
180 definitionType := json_[3].([]interface{})[1].([]interface{})[0].([]interface{})[x].([]interface{})[0]
181 if definitionType == nil {
182 definitionType = "unknown"
183 }
184
185 definitions[definitionType.(string)] = []map[string]interface{}{}
186
187 for i := 0; i < len(json_[3].([]interface{})[1].([]interface{})[0].([]interface{})[x].([]interface{})[1].([]interface{})); i++ {
188 definitionBox := json_[3].([]interface{})[1].([]interface{})[0].([]interface{})[x].([]interface{})[1].([]interface{})[i].([]interface{})
189 definitions[definitionType.(string)] = append(definitions[definitionType.(string)], map[string]interface{}{})
190
191 if len(definitionBox) > 4 && definitionBox[4] != nil &&
192 len(definitionBox[4].([]interface{})) > 0 && definitionBox[4].([]interface{})[0] != nil &&
193 len(definitionBox[4].([]interface{})[0].([]interface{})) > 0 && definitionBox[4].([]interface{})[0].([]interface{})[0] != nil {
194 definitions[definitionType.(string)][i]["dictionary"] = definitionBox[4].([]interface{})[0].([]interface{})[0]
195 }
196
197 if len(definitionBox) > 0 && definitionBox[0] != nil {
198 definitions[definitionType.(string)][i]["definition"] = definitionBox[0]
199 }
200
201 if len(definitionBox) > 1 && definitionBox[1] != nil {
202 definitions[definitionType.(string)][i]["use_in_sentence"] = definitionBox[1]
203 }
204
205 if len(definitionBox) > 5 && definitionBox[5] != nil {
206 definitions[definitionType.(string)][i]["synonyms"] = map[string][]string{}
207 synonyms := definitionBox[5].([]interface{})
208 synonymsMap := make(map[string][]string)
209
210 for _, synonymBox := range synonyms {
211 synonymType := ""
212 if len(synonymBox.([]interface{})) > 1 && synonymBox.([]interface{})[1] != nil &&
213 len(synonymBox.([]interface{})[1].([]interface{})) > 0 && synonymBox.([]interface{})[1].([]interface{})[0] != nil {
214 synonymType = synonymBox.([]interface{})[1].([]interface{})[0].([]interface{})[0].(string)
215 }
216
217 if len(synonymBox.([]interface{})) > 0 && synonymBox.([]interface{})[0] != nil {
218 synonymList := synonymBox.([]interface{})[0].([]interface{})
219 synonymsMap[synonymType] = []string{}
220 for _, synonymTypeWord := range synonymList {
221 synonymsMap[synonymType] = append(synonymsMap[synonymType], synonymTypeWord.([]interface{})[0].(string))
222 }
223 }
224 }
225
226 definitions[definitionType.(string)][i]["synonyms"] = synonymsMap
227 }
228 }
229 }
230 }
231 }
232
233 if len(json_) > 3 && json_[3] != nil &&
234 len(json_[3].([]interface{})) > 5 && json_[3].([]interface{})[5] != nil &&
235 len(json_[3].([]interface{})[5].([]interface{})) > 0 && json_[3].([]interface{})[5].([]interface{})[0] != nil {
236 translationBox := json_[3].([]interface{})[5].([]interface{})[0].([]interface{})
237 for x := 0; x < len(translationBox); x++ {
238 if len(translationBox[x].([]interface{})) > 0 {
239 translationType := translationBox[x].([]interface{})[0]
240 if translationType == nil {
241 translationType = "unknown"
242 }
243 translations[translationType.(string)] = make(map[string]map[string]interface{})
244
245 if len(translationBox[x].([]interface{})) > 1 && translationBox[x].([]interface{})[1] != nil {
246 translationNamesBox := translationBox[x].([]interface{})[1].([]interface{})
247 for i := 0; i < len(translationNamesBox); i++ {
248 if len(translationNamesBox[i].([]interface{})) > 0 && translationNamesBox[i].([]interface{})[0] != nil {
249 translationName := translationNamesBox[i].([]interface{})[0].(string)
250 translations[translationType.(string)][translationName] = make(map[string]interface{})
251 if len(translationNamesBox[i].([]interface{})) > 3 && translationNamesBox[i].([]interface{})[3] != nil {
252 frequency := fmt.Sprintf("%d", int(translationNamesBox[i].([]interface{})[3].(float64)))
253 if frequency == "3" {
254 frequency = "1"
255 } else if frequency == "1" {
256 frequency = "3"
257 }
258 translations[translationType.(string)][translationName]["frequency"] = frequency + "/3"
259
260 translations[translationType.(string)][translationName]["words"] = []string{}
261 if len(translationNamesBox[i].([]interface{})) > 2 && translationNamesBox[i].([]interface{})[2] != nil {
262 for z := 0; z < len(translationNamesBox[i].([]interface{})[2].([]interface{})); z++ {
263 word := translationNamesBox[i].([]interface{})[2].([]interface{})[z].(string)
264 translations[translationType.(string)][translationName]["words"] = append(translations[translationType.(string)][translationName]["words"].([]string), word)
265 }
266 }
267 }
268 }
269 }
270 }
271 }
272 }
273 }
274
275 if len(json_) > 0 && json_[0] != nil && len(json_[0].([]interface{})) > 2 && json_[0].([]interface{})[2] != nil {
276 from = json_[0].([]interface{})[2].(string)
277 }
278
279 }
280 }
281
282 if from == "auto" {
283 from = ""
284 }
285
286 return TranslationResult{
287 SourceLanguage: from,
288 Definitions: definitions,
289 Translations: translations,
290 TranslatedText: translatedText,
291 }, nil
292}
Note: See TracBrowser for help on using the repository browser.