Dhudean commited on
Commit
0d39baf
·
1 Parent(s): 9460ee9
Files changed (7) hide show
  1. check/check.go +19 -19
  2. common/config/config.go +103 -10
  3. common/constants.go +3 -1
  4. common/token.go +1 -1
  5. controller/chat.go +122 -119
  6. job/cookie.go +35 -0
  7. main.go +5 -0
check/check.go CHANGED
@@ -44,25 +44,25 @@ func CheckEnvVariable() {
44
  }
45
  }
46
 
47
- if config.SessionImageChatMapStr != "" {
48
- pattern := `^([a-zA-Z0-9\-\/]+=([a-zA-Z0-9\-\.]+))(,[a-zA-Z0-9\-\/]+=([a-zA-Z0-9\-\.]+))*`
49
- match, _ := regexp.MatchString(pattern, config.SessionImageChatMapStr)
50
- if !match {
51
- logger.FatalLog("环境变量 SESSION_IMAGE_CHAT_MAP 设置有误")
52
- } else {
53
- sessionImageChatMap := make(map[string]string)
54
- pairs := strings.Split(config.SessionImageChatMapStr, ",")
55
-
56
- for _, pair := range pairs {
57
- kv := strings.Split(pair, "=")
58
- sessionImageChatMap["session_id="+kv[0]] = kv[1]
59
- }
60
-
61
- config.SessionImageChatMap = sessionImageChatMap
62
- }
63
- } else {
64
- logger.SysLog("环境变量 SESSION_IMAGE_CHAT_MAP 未设置,生图可能会异常")
65
- }
66
 
67
  logger.SysLog("environment variable check passed.")
68
  }
 
44
  }
45
  }
46
 
47
+ //if config.SessionImageChatMapStr != "" {
48
+ // pattern := `^([a-zA-Z0-9\-\/]+=([a-zA-Z0-9\-\.]+))(,[a-zA-Z0-9\-\/]+=([a-zA-Z0-9\-\.]+))*`
49
+ // match, _ := regexp.MatchString(pattern, config.SessionImageChatMapStr)
50
+ // if !match {
51
+ // logger.FatalLog("环境变量 SESSION_IMAGE_CHAT_MAP 设置有误")
52
+ // } else {
53
+ // sessionImageChatMap := make(map[string]string)
54
+ // pairs := strings.Split(config.SessionImageChatMapStr, ",")
55
+ //
56
+ // for _, pair := range pairs {
57
+ // kv := strings.Split(pair, "=")
58
+ // sessionImageChatMap["session_id="+kv[0]] = kv[1]
59
+ // }
60
+ //
61
+ // config.SessionImageChatMap = sessionImageChatMap
62
+ // }
63
+ //} else {
64
+ // logger.SysLog("环境变量 SESSION_IMAGE_CHAT_MAP 未设置,生图可能会异常")
65
+ //}
66
 
67
  logger.SysLog("environment variable check passed.")
68
  }
common/config/config.go CHANGED
@@ -15,7 +15,8 @@ var ApiSecret = os.Getenv("API_SECRET")
15
  var ApiSecrets = strings.Split(os.Getenv("API_SECRET"), ",")
16
 
17
  var GSCookie = os.Getenv("GS_COOKIE")
18
- var GSCookies = strings.Split(os.Getenv("GS_COOKIE"), ",")
 
19
 
20
  // var IpBlackList = os.Getenv("IP_BLACK_LIST")
21
  var IpBlackList = strings.Split(os.Getenv("IP_BLACK_LIST"), ",")
@@ -26,13 +27,15 @@ var AutoModelChatMapType = env.Int("AUTO_MODEL_CHAT_MAP_TYPE", 1)
26
  var YesCaptchaClientKey = env.String("YES_CAPTCHA_CLIENT_KEY", "")
27
  var CheatUrl = env.String("CHEAT_URL", "https://gs-cheat.aytsao.cn/genspark/create/req/body")
28
 
 
 
29
  // 路由前缀
30
  var RoutePrefix = env.String("ROUTE_PREFIX", "")
31
  var ModelChatMapStr = env.String("MODEL_CHAT_MAP", "")
32
  var ModelChatMap = make(map[string]string)
33
- var SessionImageChatMapStr = env.String("SESSION_IMAGE_CHAT_MAP", "")
34
  var SessionImageChatMap = make(map[string]string)
35
  var GlobalSessionManager *SessionManager
 
36
  var YescaptchaClient *yescaptcha.Client
37
 
38
  var AllDialogRecordEnable = os.Getenv("ALL_DIALOG_RECORD_ENABLE")
@@ -52,26 +55,108 @@ var (
52
  RequestRateLimitDuration int64 = 1 * 60
53
  )
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  type CookieManager struct {
56
  Cookies []string
57
  currentIndex int
58
  mu sync.Mutex
59
  }
60
 
61
- func NewCookieManager() *CookieManager {
62
- cookies := strings.Split(os.Getenv("GS_COOKIE"), ",")
63
- // 过滤空字符串
64
- var validCookies []string
65
- for _, cookie := range cookies {
66
- if strings.TrimSpace(cookie) != "" {
 
 
 
67
 
 
 
 
 
 
 
 
 
68
  if !strings.Contains(cookie, "session_id=") {
69
  cookie = "session_id=" + cookie
70
-
71
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
- validCookies = append(validCookies, cookie)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  }
 
 
 
75
  }
76
 
77
  return &CookieManager{
@@ -80,6 +165,14 @@ func NewCookieManager() *CookieManager {
80
  }
81
  }
82
 
 
 
 
 
 
 
 
 
83
  func (cm *CookieManager) RemoveCookie(cookieToRemove string) error {
84
  cm.mu.Lock()
85
  defer cm.mu.Unlock()
 
15
  var ApiSecrets = strings.Split(os.Getenv("API_SECRET"), ",")
16
 
17
  var GSCookie = os.Getenv("GS_COOKIE")
18
+
19
+ //var GSCookies = strings.Split(os.Getenv("GS_COOKIE"), ",")
20
 
21
  // var IpBlackList = os.Getenv("IP_BLACK_LIST")
22
  var IpBlackList = strings.Split(os.Getenv("IP_BLACK_LIST"), ",")
 
27
  var YesCaptchaClientKey = env.String("YES_CAPTCHA_CLIENT_KEY", "")
28
  var CheatUrl = env.String("CHEAT_URL", "https://gs-cheat.aytsao.cn/genspark/create/req/body")
29
 
30
+ var RateLimitCookieLockDuration = env.Int("RATE_LIMIT_COOKIE_LOCK_DURATION", 10*60)
31
+
32
  // 路由前缀
33
  var RoutePrefix = env.String("ROUTE_PREFIX", "")
34
  var ModelChatMapStr = env.String("MODEL_CHAT_MAP", "")
35
  var ModelChatMap = make(map[string]string)
 
36
  var SessionImageChatMap = make(map[string]string)
37
  var GlobalSessionManager *SessionManager
38
+ var SessionImageChatMapStr = env.String("SESSION_IMAGE_CHAT_MAP", "")
39
  var YescaptchaClient *yescaptcha.Client
40
 
41
  var AllDialogRecordEnable = os.Getenv("ALL_DIALOG_RECORD_ENABLE")
 
55
  RequestRateLimitDuration int64 = 1 * 60
56
  )
57
 
58
+ type RateLimitCookie struct {
59
+ ExpirationTime time.Time // 过期时间
60
+ }
61
+
62
+ var (
63
+ rateLimitCookies sync.Map // 使用 sync.Map 管理限速 Cookie
64
+ )
65
+
66
+ func AddRateLimitCookie(cookie string, expirationTime time.Time) {
67
+ rateLimitCookies.Store(cookie, RateLimitCookie{
68
+ ExpirationTime: expirationTime,
69
+ })
70
+ //fmt.Printf("Storing cookie: %s with value: %+v\n", cookie, RateLimitCookie{ExpirationTime: expirationTime})
71
+ }
72
+
73
  type CookieManager struct {
74
  Cookies []string
75
  currentIndex int
76
  mu sync.Mutex
77
  }
78
 
79
+ var (
80
+ GSCookies []string // 存储所有的 cookies
81
+ cookiesMutex sync.Mutex // 保护 GSCookies 的互斥锁
82
+ )
83
+
84
+ // InitGSCookies 初始化 GSCookies
85
+ func InitGSCookies() {
86
+ cookiesMutex.Lock()
87
+ defer cookiesMutex.Unlock()
88
 
89
+ GSCookies = []string{}
90
+
91
+ // 从环境变量中读取 GS_COOKIE 并拆分为切片
92
+ cookieStr := os.Getenv("GS_COOKIE")
93
+ if cookieStr != "" {
94
+
95
+ for _, cookie := range strings.Split(cookieStr, ",") {
96
+ // 如果 cookie 不包含 "session_id=",则添加前缀
97
  if !strings.Contains(cookie, "session_id=") {
98
  cookie = "session_id=" + cookie
 
99
  }
100
+ GSCookies = append(GSCookies, cookie)
101
+ }
102
+ }
103
+ }
104
+
105
+ // RemoveCookie 删除指定的 cookie(支持并发)
106
+ func RemoveCookie(cookieToRemove string) {
107
+ cookiesMutex.Lock()
108
+ defer cookiesMutex.Unlock()
109
+
110
+ // 创建一个新的切片,过滤掉需要删除的 cookie
111
+ var newCookies []string
112
+ for _, cookie := range GetGSCookies() {
113
+ if cookie != cookieToRemove {
114
+ newCookies = append(newCookies, cookie)
115
+ }
116
+ }
117
+
118
+ // 更新 GSCookies
119
+ GSCookies = newCookies
120
+ }
121
+
122
+ // GetGSCookies 获取 GSCookies 的副本
123
+ func GetGSCookies() []string {
124
+ //cookiesMutex.Lock()
125
+ //defer cookiesMutex.Unlock()
126
+
127
+ // 返回 GSCookies 的副本,避免外部直接修改
128
+ cookiesCopy := make([]string, len(GSCookies))
129
+ copy(cookiesCopy, GSCookies)
130
+ return cookiesCopy
131
+ }
132
 
133
+ // NewCookieManager 创建 CookieManager
134
+ func NewCookieManager() *CookieManager {
135
+ var validCookies []string
136
+ // 遍历 GSCookies
137
+ for _, cookie := range GetGSCookies() {
138
+ cookie = strings.TrimSpace(cookie)
139
+ if cookie == "" {
140
+ continue // 忽略空字符串
141
+ }
142
+
143
+ // 检查是否在 RateLimitCookies 中
144
+ if value, ok := rateLimitCookies.Load(cookie); ok {
145
+ rateLimitCookie, ok := value.(RateLimitCookie) // 正确转换为 RateLimitCookie
146
+ if !ok {
147
+ continue
148
+ }
149
+ if rateLimitCookie.ExpirationTime.After(time.Now()) {
150
+ // 如果未过期,忽略该 cookie
151
+ continue
152
+ } else {
153
+ // 如果已过期,从 RateLimitCookies 中删除
154
+ rateLimitCookies.Delete(cookie)
155
+ }
156
  }
157
+
158
+ // 添加到有效 cookie 列表
159
+ validCookies = append(validCookies, cookie)
160
  }
161
 
162
  return &CookieManager{
 
165
  }
166
  }
167
 
168
+ func IsRateLimited(cookie string) bool {
169
+ if value, ok := rateLimitCookies.Load(cookie); ok {
170
+ rateLimitCookie := value.(RateLimitCookie)
171
+ return rateLimitCookie.ExpirationTime.After(time.Now())
172
+ }
173
+ return false
174
+ }
175
+
176
  func (cm *CookieManager) RemoveCookie(cookieToRemove string) error {
177
  cm.mu.Lock()
178
  defer cm.mu.Unlock()
common/constants.go CHANGED
@@ -3,7 +3,7 @@ package common
3
  import "time"
4
 
5
  var StartTime = time.Now().Unix() // unit: second
6
- var Version = "v1.10.0" // this hard coding will be replaced automatically when building, no need to manually change
7
 
8
  var DefaultOpenaiModelList = []string{
9
  "gpt-4o",
@@ -21,6 +21,7 @@ var DefaultOpenaiModelList = []string{
21
  "ideogram",
22
  "recraft-v3",
23
  "dall-e-3",
 
24
  }
25
 
26
  var TextModelList = []string{
@@ -47,4 +48,5 @@ var ImageModelList = []string{
47
  "ideogram",
48
  "recraft-v3",
49
  "dall-e-3",
 
50
  }
 
3
  import "time"
4
 
5
  var StartTime = time.Now().Unix() // unit: second
6
+ var Version = "v1.10.10" // this hard coding will be replaced automatically when building, no need to manually change
7
 
8
  var DefaultOpenaiModelList = []string{
9
  "gpt-4o",
 
21
  "ideogram",
22
  "recraft-v3",
23
  "dall-e-3",
24
+ "imagen3",
25
  }
26
 
27
  var TextModelList = []string{
 
48
  "ideogram",
49
  "recraft-v3",
50
  "dall-e-3",
51
+ "imagen3",
52
  }
common/token.go CHANGED
@@ -50,7 +50,7 @@ func getTokenEncoder(model string) *tiktoken.Tiktoken {
50
  if ok {
51
  tokenEncoder, err := tiktoken.EncodingForModel(model)
52
  if err != nil {
53
- logger.SysError(fmt.Sprintf("[IGNORE] | failed to get token encoder for model %s: %s, using encoder for gpt-3.5-turbo", model, err.Error()))
54
  tokenEncoder = defaultTokenEncoder
55
  }
56
  tokenEncoderMap[model] = tokenEncoder
 
50
  if ok {
51
  tokenEncoder, err := tiktoken.EncodingForModel(model)
52
  if err != nil {
53
+ //logger.SysError(fmt.Sprintf("[IGNORE] | failed to get token encoder for model %s: %s, using encoder for gpt-3.5-turbo", model, err.Error()))
54
  tokenEncoder = defaultTokenEncoder
55
  }
56
  tokenEncoderMap[model] = tokenEncoder
controller/chat.go CHANGED
@@ -68,6 +68,7 @@ func ChatForOpenAI(c *gin.Context) {
68
  }
69
 
70
  // 初始化cookie
 
71
  cookieManager := config.NewCookieManager()
72
  cookie, err := cookieManager.GetRandomCookie()
73
  if err != nil {
@@ -363,27 +364,6 @@ func createRequestBody(c *gin.Context, client cycletls.CycleTLS, cookie string,
363
  models = common.MixtureModelList
364
  }
365
 
366
- //gRecaptchaToken := ""
367
- //if config.YesCaptchaClientKey != "" {
368
- // // 创建上下文,设置超时
369
- // ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
370
- // defer cancel()
371
- // // 准备请求参数
372
- // req := yescaptcha.RecaptchaV3Request{
373
- // WebsiteURL: "https://www.genspark.ai/",
374
- // WebsiteKey: "6Leq7KYqAAAAAGdd1NaUBJF9dHTPAKP7DcnaRc66",
375
- // PageAction: "copilot",
376
- // }
377
- //
378
- // // 解决验证码
379
- // response, err := config.YescaptchaClient.SolveRecaptchaV3(ctx, req)
380
- // if err != nil {
381
- // return map[string]interface{}{}, err
382
- // }
383
- //
384
- // gRecaptchaToken = response
385
- //}
386
-
387
  // 创建请求体
388
  requestBody := map[string]interface{}{
389
  "type": chatType,
@@ -396,7 +376,6 @@ func createRequestBody(c *gin.Context, client cycletls.CycleTLS, cookie string,
396
  "writingContent": nil,
397
  "request_web_knowledge": requestWebKnowledge,
398
  },
399
- //"g_recaptcha_token": gRecaptchaToken,
400
  }
401
 
402
  logger.Debug(c.Request.Context(), fmt.Sprintf("RequestBody: %v", requestBody))
@@ -406,7 +385,6 @@ func createRequestBody(c *gin.Context, client cycletls.CycleTLS, cookie string,
406
  !strings.HasPrefix(config.CheatUrl, "https://")) {
407
  return requestBody, nil
408
  } else {
409
- // 发送请求到本地测试接口
410
  jsonData, err := json.Marshal(requestBody)
411
  if err != nil {
412
  return nil, fmt.Errorf("marshal request body error: %v", err)
@@ -430,26 +408,6 @@ func createRequestBody(c *gin.Context, client cycletls.CycleTLS, cookie string,
430
  }
431
 
432
  func createImageRequestBody(c *gin.Context, cookie string, openAIReq *model.OpenAIImagesGenerationRequest, chatId string) (map[string]interface{}, error) {
433
- //gRecaptchaToken := ""
434
- //if config.YesCaptchaClientKey != "" {
435
- // // 创建上下文,设置超时
436
- // ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
437
- // defer cancel()
438
- // // 准备请求参数
439
- // req := yescaptcha.RecaptchaV3Request{
440
- // WebsiteURL: "https://www.genspark.ai/",
441
- // WebsiteKey: "6Leq7KYqAAAAAGdd1NaUBJF9dHTPAKP7DcnaRc66",
442
- // PageAction: "copilot",
443
- // }
444
- //
445
- // // 解决验证码
446
- // response, err := config.YescaptchaClient.SolveRecaptchaV3(ctx, req)
447
- // if err != nil {
448
- // return map[string]interface{}{}, err
449
- // }
450
- //
451
- // gRecaptchaToken = response
452
- //}
453
 
454
  if openAIReq.Model == "dall-e-3" {
455
  openAIReq.Model = "dalle-3"
@@ -528,13 +486,13 @@ func createImageRequestBody(c *gin.Context, cookie string, openAIReq *model.Open
528
  }
529
  var currentQueryString string
530
  if len(chatId) != 0 {
531
- currentQueryString = fmt.Sprintf("id=%s&type=%s", chatId, chatType)
532
  } else {
533
- currentQueryString = fmt.Sprintf("type=%s", chatId, chatType)
534
  }
535
 
536
  // 创建请求体
537
- return map[string]interface{}{
538
  "type": "COPILOT_MOA_IMAGE",
539
  //"current_query_string": "type=COPILOT_MOA_IMAGE",
540
  "current_query_string": currentQueryString,
@@ -547,8 +505,35 @@ func createImageRequestBody(c *gin.Context, cookie string, openAIReq *model.Open
547
  "imageModelMap": map[string]interface{}{},
548
  "writingContent": nil,
549
  },
550
- //"g_recaptcha_token": gRecaptchaToken,
551
- }, nil
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
552
  }
553
 
554
  // createStreamResponse 创建流式响应
@@ -873,10 +858,14 @@ func handleStreamRequest(c *gin.Context, client cycletls.CycleTLS, cookie string
873
  case common.IsRateLimit(data):
874
  isRateLimit = true
875
  logger.Warnf(ctx, "Cookie rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
 
876
  break SSELoop // 使用 label 跳出 SSE 循环
877
  case common.IsFreeLimit(data):
878
  isRateLimit = true
879
  logger.Warnf(ctx, "Cookie free rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
 
 
 
880
  break SSELoop // 使用 label 跳出 SSE 循环
881
  case common.IsNotLogin(data):
882
  isRateLimit = true
@@ -1086,7 +1075,6 @@ func makeStreamRequest(c *gin.Context, client cycletls.CycleTLS, jsonData []byte
1086
  // }
1087
  func handleNonStreamRequest(c *gin.Context, client cycletls.CycleTLS, cookie string, cookieManager *config.CookieManager, requestBody map[string]interface{}, modelName string, searchModel bool) {
1088
  const (
1089
- errNoValidCookies = "No valid cookies available"
1090
  errCloudflareChallengeMsg = "Detected Cloudflare Challenge Page"
1091
  errCloudflareBlock = "CloudFlare: Sorry, you have been blocked"
1092
  errServerErrMsg = "An error occurred with the current request, please try again."
@@ -1138,10 +1126,14 @@ func handleNonStreamRequest(c *gin.Context, client cycletls.CycleTLS, cookie str
1138
  case common.IsRateLimit(line):
1139
  isRateLimit = true
1140
  logger.Warnf(ctx, "Cookie rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
 
1141
  break
1142
  case common.IsFreeLimit(line):
1143
  isRateLimit = true
1144
  logger.Warnf(ctx, "Cookie free rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
 
 
 
1145
  break
1146
  case common.IsNotLogin(line):
1147
  isRateLimit = true
@@ -1319,31 +1311,31 @@ func ImageProcess(c *gin.Context, client cycletls.CycleTLS, openAIReq model.Open
1319
  )
1320
 
1321
  var (
1322
- sessionImageChatManager *config.SessionMapManager
1323
- maxRetries int
1324
- cookie string
1325
- chatId string
1326
  )
1327
 
1328
  cookieManager := config.NewCookieManager()
1329
- sessionImageChatManager = config.NewSessionMapManager()
1330
  ctx := c.Request.Context()
1331
 
1332
  // Initialize session manager and get initial cookie
1333
- if len(config.SessionImageChatMap) == 0 {
1334
- logger.Warnf(ctx, "未配置环境变量 SESSION_IMAGE_CHAT_MAP, 可能会生图失败!")
1335
- maxRetries = len(cookieManager.Cookies)
1336
 
1337
- var err error
1338
- cookie, err = cookieManager.GetRandomCookie()
1339
- if err != nil {
1340
- logger.Errorf(ctx, "Failed to get initial cookie: %v", err)
1341
- return nil, fmt.Errorf(errNoValidCookies)
1342
- }
1343
- } else {
1344
- maxRetries = sessionImageChatManager.GetSize()
1345
- cookie, chatId, _ = sessionImageChatManager.GetRandomKeyValue()
1346
  }
 
 
 
 
1347
 
1348
  for attempt := 0; attempt < maxRetries; attempt++ {
1349
  // Create request body
@@ -1373,64 +1365,68 @@ func ImageProcess(c *gin.Context, client cycletls.CycleTLS, openAIReq model.Open
1373
  switch {
1374
  case common.IsRateLimit(body):
1375
  logger.Warnf(ctx, "Cookie rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1376
- if sessionImageChatManager != nil {
1377
- cookie, chatId, err = sessionImageChatManager.GetNextKeyValue()
1378
- if err != nil {
1379
- logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1380
- c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1381
- return nil, fmt.Errorf(errNoValidCookies)
1382
- }
1383
- } else {
1384
- //cookieManager := config.NewCookieManager()
1385
- cookie, err = cookieManager.GetNextCookie()
1386
- if err != nil {
1387
- logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1388
- c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1389
- return nil, fmt.Errorf(errNoValidCookies)
1390
- }
 
1391
  }
1392
  continue
1393
  case common.IsFreeLimit(body):
1394
  logger.Warnf(ctx, "Cookie free rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1395
- if sessionImageChatManager != nil {
1396
- cookie, chatId, err = sessionImageChatManager.GetNextKeyValue()
1397
- if err != nil {
1398
- logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1399
- c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1400
- return nil, fmt.Errorf(errNoValidCookies)
1401
- }
1402
- } else {
1403
- //cookieManager := config.NewCookieManager()
1404
- cookie, err = cookieManager.GetNextCookie()
1405
- if err != nil {
1406
- logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1407
- c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1408
- return nil, fmt.Errorf(errNoValidCookies)
1409
- }
 
 
 
1410
  }
1411
  continue
1412
  case common.IsNotLogin(body):
1413
- logger.Warnf(ctx, "Cookie free rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1414
- if sessionImageChatManager != nil {
1415
- //sessionImageChatManager.RemoveKey(cookie)
1416
- cookie, chatId, err = sessionImageChatManager.GetNextKeyValue()
1417
- if err != nil {
1418
- logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1419
- c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1420
- return nil, fmt.Errorf(errNoValidCookies)
1421
- }
1422
- } else {
1423
- //cookieManager := config.NewCookieManager()
1424
- //err := cookieManager.RemoveCookie(cookie)
1425
- //if err != nil {
1426
- // logger.Errorf(ctx, "Failed to remove cookie: %v", err)
 
 
 
 
 
 
1427
  //}
1428
- cookie, err = cookieManager.GetNextCookie()
1429
- if err != nil {
1430
- logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1431
- c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1432
- return nil, fmt.Errorf(errNoValidCookies)
1433
- }
1434
 
1435
  }
1436
  continue
@@ -1582,6 +1578,7 @@ func pollTaskStatus(c *gin.Context, client cycletls.CycleTLS, taskIDs []string,
1582
 
1583
  var result struct {
1584
  Data struct {
 
1585
  ImageURLsNowatermark []string `json:"image_urls_nowatermark"`
1586
  Status string `json:"status"`
1587
  }
@@ -1592,9 +1589,15 @@ func pollTaskStatus(c *gin.Context, client cycletls.CycleTLS, taskIDs []string,
1592
  }
1593
 
1594
  // 如果状态成功且有图片URL
1595
- if result.Data.Status == "SUCCESS" && len(result.Data.ImageURLsNowatermark) > 0 {
1596
- imageURLs = append(imageURLs, result.Data.ImageURLsNowatermark...)
1597
- break
 
 
 
 
 
 
1598
  }
1599
 
1600
  // 等待1秒后重试
 
68
  }
69
 
70
  // 初始化cookie
71
+
72
  cookieManager := config.NewCookieManager()
73
  cookie, err := cookieManager.GetRandomCookie()
74
  if err != nil {
 
364
  models = common.MixtureModelList
365
  }
366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
  // 创建请求体
368
  requestBody := map[string]interface{}{
369
  "type": chatType,
 
376
  "writingContent": nil,
377
  "request_web_knowledge": requestWebKnowledge,
378
  },
 
379
  }
380
 
381
  logger.Debug(c.Request.Context(), fmt.Sprintf("RequestBody: %v", requestBody))
 
385
  !strings.HasPrefix(config.CheatUrl, "https://")) {
386
  return requestBody, nil
387
  } else {
 
388
  jsonData, err := json.Marshal(requestBody)
389
  if err != nil {
390
  return nil, fmt.Errorf("marshal request body error: %v", err)
 
408
  }
409
 
410
  func createImageRequestBody(c *gin.Context, cookie string, openAIReq *model.OpenAIImagesGenerationRequest, chatId string) (map[string]interface{}, error) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
 
412
  if openAIReq.Model == "dall-e-3" {
413
  openAIReq.Model = "dalle-3"
 
486
  }
487
  var currentQueryString string
488
  if len(chatId) != 0 {
489
+ currentQueryString = fmt.Sprintf("id=%s&type=%s", chatId, imageType)
490
  } else {
491
+ currentQueryString = fmt.Sprintf("type=%s", imageType)
492
  }
493
 
494
  // 创建请求体
495
+ requestBody := map[string]interface{}{
496
  "type": "COPILOT_MOA_IMAGE",
497
  //"current_query_string": "type=COPILOT_MOA_IMAGE",
498
  "current_query_string": currentQueryString,
 
505
  "imageModelMap": map[string]interface{}{},
506
  "writingContent": nil,
507
  },
508
+ }
509
+
510
+ logger.Debug(c.Request.Context(), fmt.Sprintf("RequestBody: %v", requestBody))
511
+
512
+ if strings.TrimSpace(config.CheatUrl) == "" ||
513
+ (!strings.HasPrefix(config.CheatUrl, "http://") &&
514
+ !strings.HasPrefix(config.CheatUrl, "https://")) {
515
+ return requestBody, nil
516
+ } else {
517
+ jsonData, err := json.Marshal(requestBody)
518
+ if err != nil {
519
+ return nil, fmt.Errorf("marshal request body error: %v", err)
520
+ }
521
+
522
+ resp, err := http.Post(config.CheatUrl, "application/json", bytes.NewBuffer(jsonData))
523
+ if err != nil {
524
+ return nil, fmt.Errorf("send request to test api error: %v", err)
525
+ }
526
+ defer resp.Body.Close()
527
+
528
+ // 读取响应
529
+ var response map[string]interface{}
530
+ if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
531
+ return nil, fmt.Errorf("decode response error: %v", err)
532
+ }
533
+ logger.Debugf(c.Request.Context(), fmt.Sprintf("Cheat success!"))
534
+ return response, nil
535
+ }
536
+
537
  }
538
 
539
  // createStreamResponse 创建流式响应
 
858
  case common.IsRateLimit(data):
859
  isRateLimit = true
860
  logger.Warnf(ctx, "Cookie rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
861
+ config.AddRateLimitCookie(cookie, time.Now().Add(time.Duration(config.RateLimitCookieLockDuration)*time.Second))
862
  break SSELoop // 使用 label 跳出 SSE 循环
863
  case common.IsFreeLimit(data):
864
  isRateLimit = true
865
  logger.Warnf(ctx, "Cookie free rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
866
+ //config.AddRateLimitCookie(cookie, time.Now().Add(24*60*60*time.Second))
867
+ // 删除cookie
868
+ config.RemoveCookie(cookie)
869
  break SSELoop // 使用 label 跳出 SSE 循环
870
  case common.IsNotLogin(data):
871
  isRateLimit = true
 
1075
  // }
1076
  func handleNonStreamRequest(c *gin.Context, client cycletls.CycleTLS, cookie string, cookieManager *config.CookieManager, requestBody map[string]interface{}, modelName string, searchModel bool) {
1077
  const (
 
1078
  errCloudflareChallengeMsg = "Detected Cloudflare Challenge Page"
1079
  errCloudflareBlock = "CloudFlare: Sorry, you have been blocked"
1080
  errServerErrMsg = "An error occurred with the current request, please try again."
 
1126
  case common.IsRateLimit(line):
1127
  isRateLimit = true
1128
  logger.Warnf(ctx, "Cookie rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1129
+ config.AddRateLimitCookie(cookie, time.Now().Add(time.Duration(config.RateLimitCookieLockDuration)*time.Second))
1130
  break
1131
  case common.IsFreeLimit(line):
1132
  isRateLimit = true
1133
  logger.Warnf(ctx, "Cookie free rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1134
+ //config.AddRateLimitCookie(cookie, time.Now().Add(24*60*60*time.Second))
1135
+ // 删除cookie
1136
+ config.RemoveCookie(cookie)
1137
  break
1138
  case common.IsNotLogin(line):
1139
  isRateLimit = true
 
1311
  )
1312
 
1313
  var (
1314
+ //sessionImageChatManager *config.SessionMapManager
1315
+ maxRetries int
1316
+ cookie string
1317
+ chatId string
1318
  )
1319
 
1320
  cookieManager := config.NewCookieManager()
1321
+ //sessionImageChatManager = config.NewSessionMapManager()
1322
  ctx := c.Request.Context()
1323
 
1324
  // Initialize session manager and get initial cookie
1325
+ //if len(config.SessionImageChatMap) == 0 {
1326
+ //logger.Warnf(ctx, "未配置环境变量 SESSION_IMAGE_CHAT_MAP, 可能会生图失败!")
1327
+ maxRetries = len(cookieManager.Cookies)
1328
 
1329
+ var err error
1330
+ cookie, err = cookieManager.GetRandomCookie()
1331
+ if err != nil {
1332
+ logger.Errorf(ctx, "Failed to get initial cookie: %v", err)
1333
+ return nil, fmt.Errorf(errNoValidCookies)
 
 
 
 
1334
  }
1335
+ //} else {
1336
+ // maxRetries = sessionImageChatManager.GetSize()
1337
+ // cookie, chatId, _ = sessionImageChatManager.GetRandomKeyValue()
1338
+ //}
1339
 
1340
  for attempt := 0; attempt < maxRetries; attempt++ {
1341
  // Create request body
 
1365
  switch {
1366
  case common.IsRateLimit(body):
1367
  logger.Warnf(ctx, "Cookie rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1368
+ //if sessionImageChatManager != nil {
1369
+ // cookie, chatId, err = sessionImageChatManager.GetNextKeyValue()
1370
+ // if err != nil {
1371
+ // logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1372
+ // c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1373
+ // return nil, fmt.Errorf(errNoValidCookies)
1374
+ // }
1375
+ //} else {
1376
+ //cookieManager := config.NewCookieManager()
1377
+ config.AddRateLimitCookie(cookie, time.Now().Add(time.Duration(config.RateLimitCookieLockDuration)*time.Second))
1378
+ cookie, err = cookieManager.GetNextCookie()
1379
+ if err != nil {
1380
+ logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1381
+ c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1382
+ return nil, fmt.Errorf(errNoValidCookies)
1383
+ //}
1384
  }
1385
  continue
1386
  case common.IsFreeLimit(body):
1387
  logger.Warnf(ctx, "Cookie free rate limited, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1388
+ //if sessionImageChatManager != nil {
1389
+ // cookie, chatId, err = sessionImageChatManager.GetNextKeyValue()
1390
+ // if err != nil {
1391
+ // logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1392
+ // c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1393
+ // return nil, fmt.Errorf(errNoValidCookies)
1394
+ // }
1395
+ //} else {
1396
+ //cookieManager := config.NewCookieManager()
1397
+ //config.AddRateLimitCookie(cookie, time.Now().Add(24*60*60*time.Second))
1398
+ // 删除cookie
1399
+ config.RemoveCookie(cookie)
1400
+ cookie, err = cookieManager.GetNextCookie()
1401
+ if err != nil {
1402
+ logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1403
+ c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1404
+ return nil, fmt.Errorf(errNoValidCookies)
1405
+ //}
1406
  }
1407
  continue
1408
  case common.IsNotLogin(body):
1409
+ logger.Warnf(ctx, "Cookie Not Login, switching to next cookie, attempt %d/%d, COOKIE:%s", attempt+1, maxRetries, cookie)
1410
+ //if sessionImageChatManager != nil {
1411
+ // //sessionImageChatManager.RemoveKey(cookie)
1412
+ // cookie, chatId, err = sessionImageChatManager.GetNextKeyValue()
1413
+ // if err != nil {
1414
+ // logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1415
+ // c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1416
+ // return nil, fmt.Errorf(errNoValidCookies)
1417
+ // }
1418
+ //} else {
1419
+ //cookieManager := config.NewCookieManager()
1420
+ //err := cookieManager.RemoveCookie(cookie)
1421
+ //if err != nil {
1422
+ // logger.Errorf(ctx, "Failed to remove cookie: %v", err)
1423
+ //}
1424
+ cookie, err = cookieManager.GetNextCookie()
1425
+ if err != nil {
1426
+ logger.Errorf(ctx, "No more valid cookies available after attempt %d", attempt+1)
1427
+ c.JSON(http.StatusInternalServerError, gin.H{"error": errNoValidCookies})
1428
+ return nil, fmt.Errorf(errNoValidCookies)
1429
  //}
 
 
 
 
 
 
1430
 
1431
  }
1432
  continue
 
1578
 
1579
  var result struct {
1580
  Data struct {
1581
+ ImageURLs []string `json:"image_urls"`
1582
  ImageURLsNowatermark []string `json:"image_urls_nowatermark"`
1583
  Status string `json:"status"`
1584
  }
 
1589
  }
1590
 
1591
  // 如果状态成功且有图片URL
1592
+ if result.Data.Status == "SUCCESS" {
1593
+ if len(result.Data.ImageURLsNowatermark) > 0 {
1594
+ imageURLs = append(imageURLs, result.Data.ImageURLsNowatermark...)
1595
+ break
1596
+ }
1597
+ if len(result.Data.ImageURLs) > 0 {
1598
+ imageURLs = append(imageURLs, result.Data.ImageURLs...)
1599
+ break
1600
+ }
1601
  }
1602
 
1603
  // 等待1秒后重试
job/cookie.go ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package job
2
+
3
+ import (
4
+ "genspark2api/common/config"
5
+ logger "genspark2api/common/loggger"
6
+ "math/rand"
7
+ "time"
8
+ )
9
+
10
+ func LoadCookieTask() {
11
+ for {
12
+ source := rand.NewSource(time.Now().UnixNano())
13
+ randomNumber := rand.New(source).Intn(60) // 生成0到60之间的随机整数
14
+
15
+ // 计算距离下一个时间间隔
16
+ now := time.Now()
17
+ next := time.Date(now.Year(), now.Month(), now.Day(), 17, 5, 0, 0, now.Location())
18
+
19
+ // 如果当前时间已经超过9点,那么等待到第二天的9点
20
+ if now.After(next) {
21
+ next = next.Add(24 * time.Hour)
22
+ }
23
+
24
+ delay := next.Sub(now)
25
+
26
+ // 等待直到下一个间隔
27
+ time.Sleep(delay + time.Duration(randomNumber)*time.Second)
28
+
29
+ logger.SysLog("genspark2api Scheduled LoadCookieTask Task Job Start!")
30
+
31
+ config.InitGSCookies()
32
+
33
+ logger.SysLog("genspark2api Scheduled LoadCookieTask Task Job End!")
34
+ }
35
+ }
main.go CHANGED
@@ -6,6 +6,7 @@ import (
6
  "genspark2api/common"
7
  "genspark2api/common/config"
8
  logger "genspark2api/common/loggger"
 
9
  "genspark2api/middleware"
10
  "genspark2api/router"
11
  "genspark2api/yescaptcha"
@@ -27,10 +28,14 @@ func main() {
27
  var err error
28
 
29
  common.InitTokenEncoders()
 
30
  config.YescaptchaClient = yescaptcha.NewClient(config.YesCaptchaClientKey, nil)
31
 
32
  config.GlobalSessionManager = config.NewSessionManager()
33
 
 
 
 
34
  server := gin.New()
35
  server.Use(gin.Recovery())
36
  server.Use(middleware.RequestId())
 
6
  "genspark2api/common"
7
  "genspark2api/common/config"
8
  logger "genspark2api/common/loggger"
9
+ "genspark2api/job"
10
  "genspark2api/middleware"
11
  "genspark2api/router"
12
  "genspark2api/yescaptcha"
 
28
  var err error
29
 
30
  common.InitTokenEncoders()
31
+ config.InitGSCookies()
32
  config.YescaptchaClient = yescaptcha.NewClient(config.YesCaptchaClientKey, nil)
33
 
34
  config.GlobalSessionManager = config.NewSessionManager()
35
 
36
+ // 定时任务 每天9点整重载GS_COOKIES
37
+ go job.LoadCookieTask()
38
+
39
  server := gin.New()
40
  server.Use(gin.Recovery())
41
  server.Use(middleware.RequestId())