Compare commits

..

No commits in common. "d98f71d1c54e5c1483884c62e87441269a1b8318" and "62a993bb13229ced1521d69aad31bba47e957a08" have entirely different histories.

3 changed files with 87 additions and 129 deletions

114
main.go
View File

@ -2,7 +2,7 @@
* @Author: Vincent Yang * @Author: Vincent Yang
* @Date: 2023-07-01 21:45:34 * @Date: 2023-07-01 21:45:34
* @LastEditors: Vincent Yang * @LastEditors: Vincent Yang
* @LastEditTime: 2024-11-01 13:04:50 * @LastEditTime: 2024-11-01 00:42:58
* @FilePath: /DeepLX/main.go * @FilePath: /DeepLX/main.go
* @Telegram: https://t.me/missuo * @Telegram: https://t.me/missuo
* @GitHub: https://github.com/missuo * @GitHub: https://github.com/missuo
@ -131,7 +131,7 @@ func main() {
return return
} }
result, err := translate.TranslateByDeepLX(sourceLang, targetLang, translateText, tagHandling, proxyURL, "") result, err := translate.TranslateByDeepLX(sourceLang, targetLang, translateText, tagHandling, proxyURL)
if err != nil { if err != nil {
log.Fatalf("Translation failed: %s", err) log.Fatalf("Translation failed: %s", err)
} }
@ -156,68 +156,68 @@ func main() {
}) })
// Pro API endpoint, Pro Account required // Pro API endpoint, Pro Account required
r.POST("/v1/translate", authMiddleware(cfg), func(c *gin.Context) { // r.POST("/v1/translate", authMiddleware(cfg), func(c *gin.Context) {
req := PayloadFree{} // req := PayloadFree{}
c.BindJSON(&req) // c.BindJSON(&req)
sourceLang := req.SourceLang // sourceLang := req.SourceLang
targetLang := req.TargetLang // targetLang := req.TargetLang
translateText := req.TransText // translateText := req.TransText
tagHandling := req.TagHandling // tagHandling := req.TagHandling
proxyURL := cfg.Proxy // proxyURL := cfg.Proxy
dlSession := cfg.DlSession // dlSession := cfg.DlSession
if tagHandling != "" && tagHandling != "html" && tagHandling != "xml" { // if tagHandling != "" && tagHandling != "html" && tagHandling != "xml" {
c.JSON(http.StatusBadRequest, gin.H{ // c.JSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest, // "code": http.StatusBadRequest,
"message": "Invalid tag_handling value. Allowed values are 'html' and 'xml'.", // "message": "Invalid tag_handling value. Allowed values are 'html' and 'xml'.",
}) // })
return // return
} // }
cookie := c.GetHeader("Cookie") // cookie := c.GetHeader("Cookie")
if cookie != "" { // if cookie != "" {
dlSession = strings.Replace(cookie, "dl_session=", "", -1) // dlSession = strings.Replace(cookie, "dl_session=", "", -1)
} // }
if dlSession == "" { // if dlSession == "" {
c.JSON(http.StatusUnauthorized, gin.H{ // c.JSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized, // "code": http.StatusUnauthorized,
"message": "No dl_session Found", // "message": "No dl_session Found",
}) // })
return // return
} else if strings.Contains(dlSession, ".") { // } else if strings.Contains(dlSession, ".") {
c.JSON(http.StatusUnauthorized, gin.H{ // c.JSON(http.StatusUnauthorized, gin.H{
"code": http.StatusUnauthorized, // "code": http.StatusUnauthorized,
"message": "Your account is not a Pro account. Please upgrade your account or switch to a different account.", // "message": "Your account is not a Pro account. Please upgrade your account or switch to a different account.",
}) // })
return // return
} // }
result, err := translate.TranslateByDeepLX(sourceLang, targetLang, translateText, tagHandling, proxyURL, dlSession) // result, err := translate.TranslateByDeepLXPro(sourceLang, targetLang, translateText, tagHandling, dlSession, proxyURL)
if err != nil { // if err != nil {
log.Fatalf("Translation failed: %s", err) // log.Fatalf("Translation failed: %s", err)
} // }
if result.Code == http.StatusOK { // if result.Code == http.StatusOK {
c.JSON(http.StatusOK, gin.H{ // c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK, // "code": http.StatusOK,
"id": result.ID, // "id": result.ID,
"data": result.Data, // "data": result.Data,
"alternatives": result.Alternatives, // "alternatives": result.Alternatives,
"source_lang": result.SourceLang, // "source_lang": result.SourceLang,
"target_lang": result.TargetLang, // "target_lang": result.TargetLang,
"method": result.Method, // "method": result.Method,
}) // })
} else { // } else {
c.JSON(result.Code, gin.H{ // c.JSON(result.Code, gin.H{
"code": result.Code, // "code": result.Code,
"message": result.Message, // "message": result.Message,
}) // })
} // }
}) // })
// Free API endpoint, Consistent with the official API format // Free API endpoint, Consistent with the official API format
r.POST("/v2/translate", authMiddleware(cfg), func(c *gin.Context) { r.POST("/v2/translate", authMiddleware(cfg), func(c *gin.Context) {
@ -247,7 +247,7 @@ func main() {
targetLang = jsonData.TargetLang targetLang = jsonData.TargetLang
} }
result, err := translate.TranslateByDeepLX("", targetLang, translateText, "", proxyURL, "") result, err := translate.TranslateByDeepLX("", targetLang, translateText, "", proxyURL)
if err != nil { if err != nil {
log.Fatalf("Translation failed: %s", err) log.Fatalf("Translation failed: %s", err)
} }

View File

@ -2,7 +2,7 @@
* @Author: Vincent Young * @Author: Vincent Young
* @Date: 2024-09-16 11:59:24 * @Date: 2024-09-16 11:59:24
* @LastEditors: Vincent Yang * @LastEditors: Vincent Yang
* @LastEditTime: 2024-11-01 13:12:25 * @LastEditTime: 2024-11-01 00:42:43
* @FilePath: /DeepLX/translate/translate.go * @FilePath: /DeepLX/translate/translate.go
* @Telegram: https://t.me/missuo * @Telegram: https://t.me/missuo
* @GitHub: https://github.com/missuo * @GitHub: https://github.com/missuo
@ -27,7 +27,7 @@ import (
const baseURL = "https://www2.deepl.com/jsonrpc" const baseURL = "https://www2.deepl.com/jsonrpc"
// makeRequest makes an HTTP request to DeepL API // makeRequest makes an HTTP request to DeepL API
func makeRequest(postData *PostData, urlMethod string, proxyURL string, dlSession string) (gjson.Result, error) { func makeRequest(postData *PostData, urlMethod string, proxyURL string) (gjson.Result, error) {
urlFull := fmt.Sprintf("%s?client=chrome-extension,1.28.0&method=%s", baseURL, urlMethod) urlFull := fmt.Sprintf("%s?client=chrome-extension,1.28.0&method=%s", baseURL, urlMethod)
postStr := formatPostString(postData) postStr := formatPostString(postData)
@ -36,43 +36,23 @@ func makeRequest(postData *PostData, urlMethod string, proxyURL string, dlSessio
return gjson.Result{}, err return gjson.Result{}, err
} }
if dlSession != "" { // Set headers
req.Header = http.Header{ req.Header = http.Header{
"Accept": []string{"*/*"}, "Accept": []string{"*/*"},
"Accept-Language": []string{"en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh-HK;q=0.6,zh;q=0.5"}, "Accept-Language": []string{"en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh-HK;q=0.6,zh;q=0.5"},
"Authorization": []string{"None"}, "Authorization": []string{"None"},
"Cache-Control": []string{"no-cache"}, "Cache-Control": []string{"no-cache"},
"Content-Type": []string{"application/json"}, "Content-Type": []string{"application/json"},
"DNT": []string{"1"}, "DNT": []string{"1"},
"Origin": []string{"chrome-extension://cofdbpoegempjloogbagkncekinflcnj"}, "Origin": []string{"chrome-extension://cofdbpoegempjloogbagkncekinflcnj"},
"Pragma": []string{"no-cache"}, "Pragma": []string{"no-cache"},
"Priority": []string{"u=1, i"}, "Priority": []string{"u=1, i"},
"Referer": []string{"https://www.deepl.com/"}, "Referer": []string{"https://www.deepl.com/"},
"Sec-Fetch-Dest": []string{"empty"}, "Sec-Fetch-Dest": []string{"empty"},
"Sec-Fetch-Mode": []string{"cors"}, "Sec-Fetch-Mode": []string{"cors"},
"Sec-Fetch-Site": []string{"none"}, "Sec-Fetch-Site": []string{"none"},
"Sec-GPC": []string{"1"}, "Sec-GPC": []string{"1"},
"User-Agent": []string{"DeepLBrowserExtension/1.28.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"}, "User-Agent": []string{"DeepLBrowserExtension/1.28.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"},
"Cookie": []string{"dl_session=" + dlSession},
}
} else {
req.Header = http.Header{
"Accept": []string{"*/*"},
"Accept-Language": []string{"en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh-HK;q=0.6,zh;q=0.5"},
"Authorization": []string{"None"},
"Cache-Control": []string{"no-cache"},
"Content-Type": []string{"application/json"},
"DNT": []string{"1"},
"Origin": []string{"chrome-extension://cofdbpoegempjloogbagkncekinflcnj"},
"Pragma": []string{"no-cache"},
"Priority": []string{"u=1, i"},
"Referer": []string{"https://www.deepl.com/"},
"Sec-Fetch-Dest": []string{"empty"},
"Sec-Fetch-Mode": []string{"cors"},
"Sec-Fetch-Site": []string{"none"},
"Sec-GPC": []string{"1"},
"User-Agent": []string{"DeepLBrowserExtension/1.28.0 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"},
}
} }
// Setup client with proxy if provided // Setup client with proxy if provided
@ -93,20 +73,6 @@ func makeRequest(postData *PostData, urlMethod string, proxyURL string, dlSessio
} }
defer resp.Body.Close() defer resp.Body.Close()
// Check status code before processing response
if resp.StatusCode != http.StatusOK {
switch resp.StatusCode {
case http.StatusTooManyRequests:
return gjson.Result{}, fmt.Errorf("too many requests")
case http.StatusUnauthorized:
return gjson.Result{}, fmt.Errorf("unauthorized")
case http.StatusForbidden:
return gjson.Result{}, fmt.Errorf("forbidden")
default:
return gjson.Result{}, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
}
var bodyReader io.Reader var bodyReader io.Reader
if resp.Header.Get("Content-Encoding") == "br" { if resp.Header.Get("Content-Encoding") == "br" {
bodyReader = brotli.NewReader(resp.Body) bodyReader = brotli.NewReader(resp.Body)
@ -118,11 +84,12 @@ func makeRequest(postData *PostData, urlMethod string, proxyURL string, dlSessio
if err != nil { if err != nil {
return gjson.Result{}, err return gjson.Result{}, err
} }
return gjson.ParseBytes(body), nil return gjson.ParseBytes(body), nil
} }
// splitText splits the input text for translation // splitText splits the input text for translation
func splitText(text string, tagHandling bool, proxyURL string, dlSession string) (gjson.Result, error) { func splitText(text string, tagHandling bool, proxyURL string) (gjson.Result, error) {
postData := &PostData{ postData := &PostData{
Jsonrpc: "2.0", Jsonrpc: "2.0",
Method: "LMT_split_text", Method: "LMT_split_text",
@ -139,11 +106,11 @@ func splitText(text string, tagHandling bool, proxyURL string, dlSession string)
}, },
} }
return makeRequest(postData, "LMT_split_text", proxyURL, dlSession) return makeRequest(postData, "LMT_split_text", proxyURL)
} }
// TranslateByDeepLX performs translation using DeepL API // TranslateByDeepLX performs translation using DeepL API
func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string, proxyURL string, dlSession string) (DeepLXTranslationResult, error) { func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string, proxyURL string) (DeepLXTranslationResult, error) {
if text == "" { if text == "" {
return DeepLXTranslationResult{ return DeepLXTranslationResult{
Code: http.StatusNotFound, Code: http.StatusNotFound,
@ -152,7 +119,7 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
} }
// Split text first // Split text first
splitResult, err := splitText(text, tagHandling == "html" || tagHandling == "xml", proxyURL, dlSession) splitResult, err := splitText(text, tagHandling == "html" || tagHandling == "xml", proxyURL)
if err != nil { if err != nil {
return DeepLXTranslationResult{ return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable, Code: http.StatusServiceUnavailable,
@ -194,13 +161,6 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
}) })
} }
hasRegionalVariant := false
targetLangParts := strings.Split(targetLang, "-")
targetLangCode := targetLangParts[0]
if len(targetLangParts) > 1 {
hasRegionalVariant = true
}
// Prepare translation request // Prepare translation request
id := getRandomNumber() id := getRandomNumber()
postData := &PostData{ postData := &PostData{
@ -209,12 +169,11 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
ID: id, ID: id,
Params: Params{ Params: Params{
CommonJobParams: CommonJobParams{ CommonJobParams: CommonJobParams{
Mode: "translate", Mode: "translate",
RegionalVariant: map[bool]string{true: targetLang, false: ""}[hasRegionalVariant],
}, },
Lang: Lang{ Lang: Lang{
SourceLangComputed: strings.ToUpper(sourceLang), SourceLangComputed: strings.ToUpper(sourceLang),
TargetLang: strings.ToUpper(targetLangCode), TargetLang: strings.ToUpper(targetLang),
}, },
Jobs: jobs, Jobs: jobs,
Priority: 1, Priority: 1,
@ -223,7 +182,7 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
} }
// Make translation request // Make translation request
result, err := makeRequest(postData, "LMT_handle_jobs", proxyURL, dlSession) result, err := makeRequest(postData, "LMT_handle_jobs", proxyURL)
if err != nil { if err != nil {
return DeepLXTranslationResult{ return DeepLXTranslationResult{
Code: http.StatusServiceUnavailable, Code: http.StatusServiceUnavailable,
@ -273,6 +232,6 @@ func TranslateByDeepLX(sourceLang, targetLang, text string, tagHandling string,
Alternatives: alternatives, Alternatives: alternatives,
SourceLang: sourceLang, SourceLang: sourceLang,
TargetLang: targetLang, TargetLang: targetLang,
Method: map[bool]string{true: "Pro", false: "Free"}[dlSession != ""], Method: "Free",
}, nil }, nil
} }

View File

@ -2,7 +2,7 @@
* @Author: Vincent Young * @Author: Vincent Young
* @Date: 2024-09-16 11:59:24 * @Date: 2024-09-16 11:59:24
* @LastEditors: Vincent Yang * @LastEditors: Vincent Yang
* @LastEditTime: 2024-11-01 12:47:47 * @LastEditTime: 2024-11-01 00:39:49
* @FilePath: /DeepLX/translate/types.go * @FilePath: /DeepLX/translate/types.go
* @Telegram: https://t.me/missuo * @Telegram: https://t.me/missuo
* @GitHub: https://github.com/missuo * @GitHub: https://github.com/missuo
@ -21,8 +21,7 @@ type Lang struct {
// CommonJobParams represents common parameters for translation jobs // CommonJobParams represents common parameters for translation jobs
type CommonJobParams struct { type CommonJobParams struct {
Mode string `json:"mode"` Mode string `json:"mode"`
RegionalVariant string `json:"regionalVariant"`
} }
// Sentence represents a sentence in the translation request // Sentence represents a sentence in the translation request