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

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

Implemented Definitions and Translations for google

File size: 9.0 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
123 if err != nil {
124 return TranslationResult{}, err
125 }
126
[21]127 url_ := "https://translate.google.com/_/TranslateWebserverUi/data/batchexecute?rpcids=MkEWBc&rt=c"
128
129 reqJSON := []interface{}{
130 []interface{}{text, from, to, true},
131 []interface{}{nil},
132 }
133 reqJSONString, err := json.Marshal(reqJSON)
134 if err != nil {
135 fmt.Println("Error:", err)
136 return TranslationResult{}, nil
137 }
138
139 req := []interface{}{[]interface{}{[]interface{}{"MkEWBc", string(reqJSONString), nil, "generic"}}}
140
141 JSONString, _ := json.Marshal(req)
142
143 body := "f.req=" + url.QueryEscape(string(JSONString))
144
145 resp, err := http.Post(url_, "application/x-www-form-urlencoded;charset=utf-8", bytes.NewBuffer([]byte(body)))
146 if err != nil {
147 fmt.Println("Error:", err)
148 return TranslationResult{}, nil
149 }
150 defer resp.Body.Close()
151
152 bodyBytes, err := ioutil.ReadAll(resp.Body)
153 if err != nil {
154 fmt.Println("Error:", err)
155 return TranslationResult{}, nil
156 }
157 responseText := string(bodyBytes)
158
159 responseText = regexp.MustCompile(`\n\d+\n(.*)\n\d+\n`).FindStringSubmatch(responseText)[1]
160
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 data := raw[0].([]interface{})[2].(string)
169
170 var json_ []interface{}
171 err = json.Unmarshal([]byte(data), &json_)
172
173 definitions := make(map[string][]map[string]interface{})
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 translations := make(map[string]map[string]map[string]interface{})
234 if len(json_) > 3 && json_[3] != nil &&
235 len(json_[3].([]interface{})) > 5 && json_[3].([]interface{})[5] != nil &&
236 len(json_[3].([]interface{})[5].([]interface{})) > 0 && json_[3].([]interface{})[5].([]interface{})[0] != nil {
237 translationBox := json_[3].([]interface{})[5].([]interface{})[0].([]interface{})
238 for x := 0; x < len(translationBox); x++ {
239 if len(translationBox[x].([]interface{})) > 0 {
240 translationType := translationBox[x].([]interface{})[0]
241 if translationType == nil {
242 translationType = "unknown"
243 }
244 translations[translationType.(string)] = make(map[string]map[string]interface{})
245
246 if len(translationBox[x].([]interface{})) > 1 && translationBox[x].([]interface{})[1] != nil {
247 translationNamesBox := translationBox[x].([]interface{})[1].([]interface{})
248 for i := 0; i < len(translationNamesBox); i++ {
249 if len(translationNamesBox[i].([]interface{})) > 0 && translationNamesBox[i].([]interface{})[0] != nil {
250 translationName := translationNamesBox[i].([]interface{})[0].(string)
251 translations[translationType.(string)][translationName] = make(map[string]interface{})
252 if len(translationNamesBox[i].([]interface{})) > 3 && translationNamesBox[i].([]interface{})[3] != nil {
253 frequency := fmt.Sprintf("%d", int(translationNamesBox[i].([]interface{})[3].(float64)))
254 if frequency == "3" {
255 frequency = "1"
256 } else if frequency == "1" {
257 frequency = "3"
258 }
259 translations[translationType.(string)][translationName]["frequency"] = frequency + "/3"
260
261 translations[translationType.(string)][translationName]["words"] = []string{}
262 if len(translationNamesBox[i].([]interface{})) > 2 && translationNamesBox[i].([]interface{})[2] != nil {
263 for z := 0; z < len(translationNamesBox[i].([]interface{})[2].([]interface{})); z++ {
264 word := translationNamesBox[i].([]interface{})[2].([]interface{})[z].(string)
265 translations[translationType.(string)][translationName]["words"] = append(translations[translationType.(string)][translationName]["words"].([]string), word)
266 }
267 }
268 }
269 }
270 }
271 }
272 }
273 }
274 }
275
[9]276 return TranslationResult{
277 SourceLanguage: from,
[21]278 Definitions: definitions,
279 Translations: translations,
[9]280 TranslatedText: doc.Find(".result-container").Text(),
281 }, nil
282}
Note: See TracBrowser for help on using the repository browser.