fonchain-fiee/pkg/common/gpt/gpt.go
2025-02-20 19:52:27 +08:00

340 lines
7.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package gpt
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"fonchain-fiee/pkg/cache"
"io"
"net/http"
"regexp"
"strings"
"time"
)
var (
host string
telNum string
password string
)
type auth struct {
expiredAt time.Time
auth string
}
type LoginData struct {
Status int `json:"status"`
Data User `json:"data"`
Msg string `json:"msg"`
Code int `json:"code"`
Error interface{} `json:"error"`
Err string `json:"err"`
Keys []string `json:"keys"`
}
type User struct {
Token string `json:"Token"`
}
type GptRes struct {
Status int `json:"status"`
Data Data `json:"data"`
Msg string `json:"msg"`
Code int `json:"code"`
Error interface{} `json:"error"`
Err string `json:"err"`
Keys interface{} `json:"keys"`
}
type Data struct {
Answer string `json:"answer"`
}
var authObj = auth{}
func InitSet(tempHost, tel, paw string) {
host = tempHost
telNum = tel
password = paw
}
// 登陆url
func getGetLoginUrl() string {
return host + "/user/login"
}
func getGptTextUrl() string {
return host + "/chat/completion-text"
}
// getLoginAuth 冲登陆中获取 登陆标志
func getLoginAuth() (string, error) {
userRes := &LoginData{}
//登陆
bodyStr := `{"TelNum": "` + telNum + `","Password": "` + password + `"}`
// 目标URL
url := getGetLoginUrl()
fmt.Println(bodyStr)
// 创建POST请求
requestObj, err := http.NewRequest("POST", url, bytes.NewBufferString(bodyStr))
if err != nil {
fmt.Println("Error creating request:", err)
return "", err
}
// 设置Headers
requestObj.Header.Set("Content-Type", "application/json")
// 初始化HTTP客户端
client := &http.Client{}
fmt.Println(1)
// 发送请求
response, err := client.Do(requestObj)
if err != nil {
fmt.Println("Error sending POST request:", err)
return "", err
}
defer response.Body.Close()
fmt.Println(2)
// 检查HTTP响应状态码
if response.StatusCode != http.StatusOK {
fmt.Printf("Error: HTTP status code is %d\n", response.StatusCode)
return "", errors.New(fmt.Sprintf("Error: HTTP status code is %d\n", response.StatusCode))
}
fmt.Println(3)
// 直接将响应内容复制到标准输出
body, err := io.ReadAll(response.Body)
if err != nil {
// 处理复制内容时出现的错误
fmt.Printf("Error copying response to stdout: %s\n", err)
return "", err
}
fmt.Println(4)
err = json.Unmarshal(body, &userRes)
if err != nil {
// 处理复制内容时出现的错误
fmt.Printf("json.Error copying response to stdout: %s\n", err)
return "", err
}
if userRes.Status != 0 {
// 处理复制内容时出现的错误
fmt.Printf("json.Error copying response to stdout: %s\n", err)
return "", errors.New("翻译失败,帐号信息 " + userRes.Msg)
}
return userRes.Data.Token, nil
}
// getLoginAuth 获取登陆标志,过期则重新获取
func getAuth() (string, error) {
fmt.Println(authObj.expiredAt)
fmt.Println(authObj.expiredAt.After(time.Now()))
//帐号未过期
if authObj.expiredAt.After(time.Now()) {
return authObj.auth, nil
}
//重新获取
authCode, err := getLoginAuth()
if err != nil {
return "", err
}
authObj.expiredAt = time.Now().Add(2 * time.Hour)
authObj.auth = authCode
return authCode, err
}
func setAuthExpire() {
authObj.expiredAt = authObj.expiredAt.AddDate(-1, 0, 0)
}
// GptContentLand gpt翻译成语言
func GptContentLand(content, land string) (newContent string, err error) {
if isDefaultLang(land) {
return content, nil
}
val := cache.RedisClient.HGet(cache.GetLangHashKey(land), content).Val()
if val != "" {
return val, nil
}
newContent, err = realGptContentLand(content, land)
if err != nil {
return "", err
}
cache.RedisClient.HSet(cache.GetLangHashKey(land), content, newContent)
return newContent, err
}
func isDefaultLang(lang string) bool {
if lang != "Ja" && lang != "ZhTW" && lang != "EN" {
return true
}
return false
}
// realGptContentLand gpt翻译成语言
func realGptContentLand(content, land string) (newContent string, err error) {
if land == "Ja" {
newContent, err = gptContent("翻译成日语:" + content)
fmt.Println(newContent)
} else if land == "ZhTW" {
newContent, err = gptContent("翻译成繁体:" + content)
} else if land == "EN" {
newContent, err = gptContent("翻译成英语:" + content)
if err == nil {
parts := strings.Split(newContent, "\n")
fmt.Println(newContent)
fmt.Println(parts)
if len(parts) > 1 {
newContent = parts[1]
newContent = strings.Replace(newContent, "\\", "", 0)
}
}
} else {
newContent = content
}
//去重空格
fmt.Println("1-------", newContent)
newContent = removeAfterNewline(newContent)
fmt.Println("2-------", newContent)
return newContent, err
}
func removeAfterNewline(s string) string {
// 编译正则表达式,匹配第一个换行符(包括 \n, \r\n, \r及其后的内容
re := regexp.MustCompile(`(\r\n|\r|\n|\\n).*`)
// 替换匹配部分为空字符串
return re.ReplaceAllString(s, "")
}
func gptContent(content string) (string, error) {
authCode, err := getAuth()
if err != nil {
return "", err
}
fmt.Println(content)
res, err := getGptContent(content, authCode)
if err != nil {
errMsg := err.Error()
if errMsg == "请先登陆" {
setAuthExpire()
authCode1, err1 := getAuth()
if err1 != nil {
return "", err
}
res1, err1 := getGptContent(content, authCode1)
if err1 != nil {
return "", err1
}
return res1, nil
}
return "", err
}
return res, nil
}
// GetGptContent 获取翻译
func getGptContent(content, authCode string) (string, error) {
var res *GptRes
if content == "" {
return "", errors.New("内容不能为空")
}
//增加文字的黄反鉴别
strBody := `{
"model": "gpt-4-1106-preview",
"max_tokens": 1000,
"temperature": 1,
"top_p": 1,
"presence_penalty": 0,
"frequency_penalty": 0,
"messages": [
{
"role": "user",
"content": "` + content + `"
}
],
"listUuid": "",
"stream": true
}`
// 目标URL
url := getGptTextUrl()
// 创建POST请求
requestObj, err := http.NewRequest("POST", url, bytes.NewBufferString(strBody))
if err != nil {
fmt.Println("Error creating request:", err)
return "", err
}
// 设置Headers
requestObj.Header.Set("Content-Type", "application/json")
requestObj.Header.Set("Authorization", authCode)
// 初始化HTTP客户端
client := &http.Client{}
// 发送请求
response, err := client.Do(requestObj)
if err != nil {
fmt.Println("Error sending POST request:", err)
return "", err
}
defer response.Body.Close()
// 检查HTTP响应状态码
if response.StatusCode != http.StatusOK {
fmt.Printf("Error: HTTP status code is %d\n", response.StatusCode)
return "", errors.New(fmt.Sprintf("Error: HTTP status code is %d\n", response.StatusCode))
}
// 直接将响应内容复制到标准输出
body, err := io.ReadAll(response.Body)
if err != nil {
// 处理复制内容时出现的错误
fmt.Printf("Error copying response to stdout: %s\n", err)
return "", err
}
err = json.Unmarshal(body, &res)
if err != nil {
// 处理复制内容时出现的错误
fmt.Printf("json.Error copying response to stdout: %s\n", err)
return "", err
}
if res.Status != 0 {
return "", errors.New(res.Msg)
}
return res.Data.Answer, nil
}