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

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

Fixed bug

File size: 9.4 KB
RevLine 
[9]1package engines
2
3import (
[21]4 "bytes"
[9]5 "fmt"
[21]6 "io/ioutil"
[9]7 "net/http"
8 "net/url"
9
[21]10 "encoding/json"
11 "regexp"
12
[9]13 "github.com/PuerkitoBio/goquery"
14)
15
[10]16type GoogleTranslate struct{}
[9]17
[26]18func (_ *GoogleTranslate) DisplayName() string { return "Google Translate" }
[9]19
[15]20func (_ *GoogleTranslate) getLangs(type_ string) (Language, error) {
[9]21 var langsType string
22 switch type_ {
23 case "source":
24 langsType = "sl"
25
26 case "target":
27 langsType = "tl"
28
29 default:
[23]30 return nil, fmt.Errorf("Invalid language type: %s", langsType)
[9]31 }
32
[15]33 requestURL, _ := url.Parse("https://translate.google.com/m")
[9]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
[20]52 var langs Language = make(Language)
[9]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
[15]69 langs[langCode] = a.Text()
[9]70 })
71
72 return langs, nil
73}
74
[15]75func (e *GoogleTranslate) SourceLanguages() (Language, error) {
[9]76 return e.getLangs("source")
77}
78
[15]79func (e *GoogleTranslate) TargetLanguages() (Language, error) {
[9]80 return e.getLangs("target")
81}
82
[20]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
[15]95func (_ *GoogleTranslate) Translate(text string, from, to string) (TranslationResult, error) {
96 requestURL, _ := url.Parse("https://translate.google.com/m")
[9]97
[15]98 if from == "" {
99 from = "auto"
[9]100 }
101
102 query := url.Values{}
[15]103 query.Add("sl", from)
104 query.Add("tl", to)
105 query.Add("hl", to)
[9]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
[22]119 translatedText := doc.Find(".result-container").Text()
120
[9]121 if err != nil {
122 return TranslationResult{}, err
123 }
124
[21]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)
[40]156 responseTextList := regexp.MustCompile(`\n\d+\n(.*)\n\d+\n`).FindStringSubmatch(responseText)
[22]157 definitions := make(map[string][]map[string]interface{})
158 translations := make(map[string]map[string]map[string]interface{})
[40]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 }
[21]167
[40]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)
[21]171
[40]172 var json_ []interface{}
173 err = json.Unmarshal([]byte(data), &json_)
[21]174
[40]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 }
[21]184
[40]185 definitions[definitionType.(string)] = []map[string]interface{}{}
[21]186
[40]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{}{})
[21]190
[40]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 }
[21]196
[40]197 if len(definitionBox) > 0 && definitionBox[0] != nil {
198 definitions[definitionType.(string)][i]["definition"] = definitionBox[0]
199 }
[21]200
[40]201 if len(definitionBox) > 1 && definitionBox[1] != nil {
202 definitions[definitionType.(string)][i]["use_in_sentence"] = definitionBox[1]
203 }
[21]204
[40]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)
[21]209
[40]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 }
[21]216
[40]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 }
[22]223 }
224 }
[40]225
226 definitions[definitionType.(string)][i]["synonyms"] = synonymsMap
[21]227 }
228 }
229 }
230 }
231 }
232
[40]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{})
[21]244
[40]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"
[21]259
[40]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 }
[22]266 }
[21]267 }
268 }
269 }
270 }
271 }
272 }
273 }
[23]274
[40]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
[23]279 }
[21]280 }
281
[32]282 if from == "auto" {
283 from = ""
284 }
285
[9]286 return TranslationResult{
287 SourceLanguage: from,
[21]288 Definitions: definitions,
289 Translations: translations,
[22]290 TranslatedText: translatedText,
[9]291 }, nil
292}
Note: See TracBrowser for help on using the repository browser.