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

Last change on this file since 22 was 22, checked in by manerakai, 22 months ago

Implemented Definitions and Translations in Web interface

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