From b266188a28101d75815b4e57db2ea55dff45984f Mon Sep 17 00:00:00 2001 From: eeeXun Date: Fri, 29 Dec 2023 13:31:26 +0800 Subject: [PATCH] feat: add gemini --- config.go | 4 +- internal/translate/gemini/language.go | 142 ++++++++++++++++++++++++ internal/translate/gemini/translator.go | 96 ++++++++++++++++ internal/translate/translator.go | 4 + 4 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 internal/translate/gemini/language.go create mode 100644 internal/translate/gemini/translator.go diff --git a/config.go b/config.go index 5d3ec61..ba0e451 100644 --- a/config.go +++ b/config.go @@ -50,6 +50,8 @@ func configInit() { "destination.language.chatgpt": "English", "source.language.deepl": "English", "destination.language.deepl": "English", + "source.language.gemini": "English", + "destination.language.gemini": "English", "source.language.google": "English", "destination.language.google": "English", "source.language.reverso": "English", @@ -153,7 +155,7 @@ func configInit() { uiStyle.SetSrcBorderColor(config.GetString("source.border_color")). SetDstBorderColor(config.GetString("destination.border_color")) // Set API Keys - for _, name := range []string{"ChatGPT", "DeepL"} { + for _, name := range []string{"ChatGPT", "DeepL", "Gemini"} { if config.Get(fmt.Sprintf("api_key.%s", name)) != nil { translators[name].SetAPIKey(config.GetString(fmt.Sprintf("api_key.%s", name))) } diff --git a/internal/translate/gemini/language.go b/internal/translate/gemini/language.go new file mode 100644 index 0000000..fd0e4ee --- /dev/null +++ b/internal/translate/gemini/language.go @@ -0,0 +1,142 @@ +package gemini + +var ( + // Generated from Google + lang = []string{ + "Afrikaans", + "Albanian", + "Amharic", + "Arabic", + "Armenian", + "Auto", + "Assamese", + "Aymara", + "Azerbaijani", + "Bambara", + "Basque", + "Belarusian", + "Bengali", + "Bhojpuri", + "Bosnian", + "Bulgarian", + "Catalan", + "Cebuano", + "Chinese (Simplified)", + "Chinese (Traditional)", + "Corsican", + "Croatian", + "Czech", + "Danish", + "Dhivehi", + "Dogri", + "Dutch", + "English", + "Esperanto", + "Estonian", + "Ewe", + "Filipino (Tagalog)", + "Finnish", + "French", + "Frisian", + "Galician", + "Georgian", + "German", + "Greek", + "Guarani", + "Gujarati", + "Haitian Creole", + "Hausa", + "Hawaiian", + "Hebrew", + "Hindi", + "Hmong", + "Hungarian", + "Icelandic", + "Igbo", + "Ilocano", + "Indonesian", + "Irish", + "Italian", + "Japanese", + "Javanese", + "Kannada", + "Kazakh", + "Khmer", + "Kinyarwanda", + "Konkani", + "Korean", + "Krio", + "Kurdish", + "Kurdish (Sorani)", + "Kyrgyz", + "Lao", + "Latin", + "Latvian", + "Lingala", + "Lithuanian", + "Luganda", + "Luxembourgish", + "Macedonian", + "Maithili", + "Malagasy", + "Malay", + "Malayalam", + "Maltese", + "Maori", + "Marathi", + "Meiteilon (Manipuri)", + "Mizo", + "Mongolian", + "Myanmar (Burmese)", + "Nepali", + "Norwegian", + "Nyanja (Chichewa)", + "Odia (Oriya)", + "Oromo", + "Pashto", + "Persian", + "Polish", + "Portuguese (Portugal, Brazil)", + "Punjabi", + "Quechua", + "Romanian", + "Russian", + "Samoan", + "Sanskrit", + "Scots Gaelic", + "Sepedi", + "Serbian", + "Sesotho", + "Shona", + "Sindhi", + "Sinhala (Sinhalese)", + "Slovak", + "Slovenian", + "Somali", + "Spanish", + "Sundanese", + "Swahili", + "Swedish", + "Tagalog (Filipino)", + "Tajik", + "Tamil", + "Tatar", + "Telugu", + "Thai", + "Tigrinya", + "Tsonga", + "Turkish", + "Turkmen", + "Twi (Akan)", + "Ukrainian", + "Urdu", + "Uyghur", + "Uzbek", + "Vietnamese", + "Welsh", + "Xhosa", + "Yiddish", + "Yoruba", + "Zulu", + } +) diff --git a/internal/translate/gemini/translator.go b/internal/translate/gemini/translator.go new file mode 100644 index 0000000..eb6426c --- /dev/null +++ b/internal/translate/gemini/translator.go @@ -0,0 +1,96 @@ +package gemini + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + + "github.com/eeeXun/gtt/internal/translate/core" +) + +const ( + textURL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=%s" +) + +type Translator struct { + *core.APIKey + *core.Language + *core.TTSLock + core.EngineName +} + +func NewTranslator() *Translator { + return &Translator{ + APIKey: new(core.APIKey), + Language: new(core.Language), + TTSLock: core.NewTTSLock(), + EngineName: core.NewEngineName("Gemini"), + } +} + +func (t *Translator) GetAllLang() []string { + return lang +} + +func (t *Translator) Translate(message string) (translation *core.Translation, err error) { + translation = new(core.Translation) + var data map[string]interface{} + + if len(t.GetAPIKey()) <= 0 { + return nil, errors.New("Please write your API Key in config file for " + t.GetEngineName()) + } + + urlStr := fmt.Sprintf(textURL, t.GetAPIKey()) + userData, _ := json.Marshal(map[string]interface{}{ + "contents": []map[string]interface{}{ + { + "parts": []map[string]interface{}{ + { + "text": fmt.Sprintf( + "Translate following text from %s to %s\n%s", + t.GetSrcLang(), + t.GetDstLang(), + message, + ), + }, + }, + }}, + }) + req, _ := http.NewRequest(http.MethodPost, + urlStr, + bytes.NewBuffer(userData), + ) + req.Header.Add("Content-Type", "application/json") + res, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + if err = json.Unmarshal(body, &data); err != nil { + return nil, err + } + + if len(data) <= 0 { + return nil, errors.New("Translation not found") + } + if data["error"] != nil { + return nil, errors.New(data["error"].(map[string]interface{})["message"].(string)) + } + + translation.TEXT = + data["candidates"].([]interface{})[0].(map[string]interface{})["content"].(map[string]interface{})["parts"].([]interface{})[0].(map[string]interface{})["text"].(string) + + return translation, nil +} + +func (t *Translator) PlayTTS(lang, message string) error { + defer t.ReleaseLock() + + return errors.New(t.GetEngineName() + " does not support text to speech") +} diff --git a/internal/translate/translator.go b/internal/translate/translator.go index 8e44928..15904d6 100644 --- a/internal/translate/translator.go +++ b/internal/translate/translator.go @@ -7,6 +7,7 @@ import ( "github.com/eeeXun/gtt/internal/translate/chatgpt" "github.com/eeeXun/gtt/internal/translate/core" "github.com/eeeXun/gtt/internal/translate/deepl" + "github.com/eeeXun/gtt/internal/translate/gemini" "github.com/eeeXun/gtt/internal/translate/google" "github.com/eeeXun/gtt/internal/translate/reverso" ) @@ -18,6 +19,7 @@ var ( "Bing", "ChatGPT", "DeepL", + "Gemini", "Google", "Reverso", } @@ -78,6 +80,8 @@ func NewTranslator(name string) Translator { translator = chatgpt.NewTranslator() case "DeepL": translator = deepl.NewTranslator() + case "Gemini": + translator = gemini.NewTranslator() case "Google": translator = google.NewTranslator() case "Reverso":