v/GTT
1
0
mirror of https://github.com/eeeXun/GTT.git synced 2025-05-18 00:30:40 -07:00
eeeXun cbd985b599 refactor: make Language, TTSLock and EngineName to struct in Translator
GetSrcLang, GetDstLang, SetSrcLang, SetDstLang, SwapLang are reusable
functions from translator to translator. So make Language struct.

GetEngineName is also a reusable function. So make EngineName struct.

Finally, let Translator to inherit those functions in these three
(Language, TTSLock, EngineName) structs. No need to write the duplicated
functions for each Translator.
2023-03-10 23:37:08 +08:00

151 lines
3.5 KiB
Go

package googletranslate
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"time"
"github.com/eeeXun/gtt/internal/translate/core"
"github.com/hajimehoshi/go-mp3"
"github.com/hajimehoshi/oto/v2"
)
const (
textURL = "https://translate.googleapis.com/translate_a/single?client=gtx&dt=t&dt=bd&dt=md&dt=ex&sl=%s&tl=%s&q=%s"
ttsURL = "https://translate.google.com.vn/translate_tts?ie=UTF-8&q=%s&tl=%s&client=tw-ob"
)
type GoogleTranslate struct {
*core.Language
*core.TTSLock
core.EngineName
}
func NewGoogleTranslate() *GoogleTranslate {
return &GoogleTranslate{
Language: core.NewLanguage(),
TTSLock: core.NewTTSLock(),
EngineName: core.NewEngineName("GoogleTranslate"),
}
}
func (t *GoogleTranslate) GetAllLang() []string {
return lang
}
func (t *GoogleTranslate) Translate(message string) (translation, definition, partOfSpeech string, err error) {
var data []interface{}
urlStr := fmt.Sprintf(
textURL,
langCode[t.GetSrcLang()],
langCode[t.GetDstLang()],
url.QueryEscape(message),
)
res, err := http.Get(urlStr)
if err != nil {
return "", "", "", err
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", "", "", err
}
if err = json.Unmarshal(body, &data); err != nil {
return "", "", "", err
}
if len(data) <= 0 {
return "", "", "", errors.New("Translation not found")
}
// translation = data[0]
for _, lines := range data[0].([]interface{}) {
translatedLine := lines.([]interface{})[0]
translation += fmt.Sprintf("%v", translatedLine)
}
// part of speech = data[1]
if data[1] != nil {
for _, parts := range data[1].([]interface{}) {
// part of speech
part := parts.([]interface{})[0]
partOfSpeech += fmt.Sprintf("[%v]\n", part)
for _, words := range parts.([]interface{})[2].([]interface{}) {
// dst lang
dstWord := words.([]interface{})[0]
partOfSpeech += fmt.Sprintf("\t%v:", dstWord)
// src lang
firstWord := true
for _, word := range words.([]interface{})[1].([]interface{}) {
if firstWord {
partOfSpeech += fmt.Sprintf(" %v", word)
firstWord = false
} else {
partOfSpeech += fmt.Sprintf(", %v", word)
}
}
partOfSpeech += "\n"
}
}
}
// definition = data[12]
if len(data) >= 13 && data[12] != nil {
for _, parts := range data[12].([]interface{}) {
// part of speech
part := parts.([]interface{})[0]
definition += fmt.Sprintf("[%v]\n", part)
for _, sentences := range parts.([]interface{})[1].([]interface{}) {
// definition
def := sentences.([]interface{})[0]
definition += fmt.Sprintf("\t- %v\n", def)
// example sentence
if len(sentences.([]interface{})) >= 3 && sentences.([]interface{})[2] != nil {
example := sentences.([]interface{})[2]
definition += fmt.Sprintf("\t\t\"%v\"\n", example)
}
}
}
}
return translation, definition, partOfSpeech, nil
}
func (t *GoogleTranslate) PlayTTS(lang, message string) error {
defer t.ReleaseLock()
urlStr := fmt.Sprintf(
ttsURL,
url.QueryEscape(message),
langCode[lang],
)
res, err := http.Get(urlStr)
if err != nil {
return err
}
decoder, err := mp3.NewDecoder(res.Body)
if err != nil {
return err
}
otoCtx, readyChan, err := oto.NewContext(decoder.SampleRate(), 2, 2)
if err != nil {
return err
}
<-readyChan
player := otoCtx.NewPlayer(decoder)
player.Play()
for player.IsPlaying() {
if t.IsStopped() {
return nil
}
time.Sleep(time.Millisecond)
}
if err = player.Close(); err != nil {
return err
}
return nil
}