genspark2api / common /utils.go
clash-linux's picture
Upload 46 files
a48ca26 verified
package common
import (
"encoding/base64"
"fmt"
"github.com/google/uuid"
jsoniter "github.com/json-iterator/go"
_ "github.com/pkoukk/tiktoken-go"
"math/rand"
"regexp"
"strings"
"time"
"unicode/utf8"
)
// splitStringByBytes 将字符串按照指定的字节数进行切割
func SplitStringByBytes(s string, size int) []string {
var result []string
for len(s) > 0 {
// 初始切割点
l := size
if l > len(s) {
l = len(s)
}
// 确保不在字符中间切割
for l > 0 && !utf8.ValidString(s[:l]) {
l--
}
// 如果 l 减到 0,说明 size 太小,无法容纳一个完整的字符
if l == 0 {
l = len(s)
for l > 0 && !utf8.ValidString(s[:l]) {
l--
}
}
result = append(result, s[:l])
s = s[l:]
}
return result
}
func Obj2Bytes(obj interface{}) ([]byte, error) {
// 创建一个jsonIter的Encoder
configCompatibleWithStandardLibrary := jsoniter.ConfigCompatibleWithStandardLibrary
// 将结构体转换为JSON文本并保持顺序
bytes, err := configCompatibleWithStandardLibrary.Marshal(obj)
if err != nil {
return nil, err
}
return bytes, nil
}
func GetUUID() string {
code := uuid.New().String()
code = strings.Replace(code, "-", "", -1)
return code
}
// RandomElement 返回给定切片中的随机元素
func RandomElement[T any](slice []T) (T, error) {
if len(slice) == 0 {
var zero T
return zero, fmt.Errorf("empty slice")
}
// 确保每次随机都不一样
rand.Seed(time.Now().UnixNano())
// 随机选择一个索引
index := rand.Intn(len(slice))
return slice[index], nil
}
func SliceContains(slice []string, str string) bool {
for _, item := range slice {
if strings.Contains(str, item) {
return true
}
}
return false
}
func IsImageBase64(s string) bool {
// 检查字符串是否符合数据URL的格式
if !strings.HasPrefix(s, "data:image/") || !strings.Contains(s, ";base64,") {
return false
}
if !strings.Contains(s, ";base64,") {
return false
}
// 获取";base64,"后的Base64编码部分
dataParts := strings.Split(s, ";base64,")
if len(dataParts) != 2 {
return false
}
base64Data := dataParts[1]
// 尝试Base64解码
_, err := base64.StdEncoding.DecodeString(base64Data)
return err == nil
}
func IsBase64(s string) bool {
// 检查字符串是否符合数据URL的格式
//if !strings.HasPrefix(s, "data:image/") || !strings.Contains(s, ";base64,") {
// return false
//}
if !strings.Contains(s, ";base64,") {
return false
}
// 获取";base64,"后的Base64编码部分
dataParts := strings.Split(s, ";base64,")
if len(dataParts) != 2 {
return false
}
base64Data := dataParts[1]
// 尝试Base64解码
_, err := base64.StdEncoding.DecodeString(base64Data)
return err == nil
}
//<h1 data-translate="block_headline">Sorry, you have been blocked</h1>
func IsCloudflareBlock(data string) bool {
if strings.Contains(data, `<h1 data-translate="block_headline">Sorry, you have been blocked</h1>`) {
return true
}
return false
}
func IsCloudflareChallenge(data string) bool {
// 检查基本的 HTML 结构
htmlPattern := `^<!DOCTYPE html><html.*?><head>.*?</head><body.*?>.*?</body></html>$`
// 检查 Cloudflare 特征
cfPatterns := []string{
`<title>Just a moment\.\.\.</title>`, // 标题特征
`window\._cf_chl_opt`, // CF 配置对象
`challenge-platform/h/b/orchestrate/chl_page`, // CF challenge 路径
`cdn-cgi/challenge-platform`, // CDN 路径特征
`<meta http-equiv="refresh" content="\d+">`, // 刷新 meta 标签
}
// 首先检查整体 HTML 结构
matched, _ := regexp.MatchString(htmlPattern, strings.TrimSpace(data))
if !matched {
return false
}
// 检查是否包含 Cloudflare 特征
for _, pattern := range cfPatterns {
if matched, _ := regexp.MatchString(pattern, data); matched {
return true
}
}
return false
}
func IsRateLimit(data string) bool {
if data == "Rate limit exceeded cf1" || data == "Rate limit exceeded cf2" {
return true
}
return false
}
func IsNotLogin(data string) bool {
if strings.Contains(data, `{"status":-5,"message":"not login","data":{}}`) {
return true
}
return false
}
func IsServerError(data string) bool {
if data == "Internal Server Error" {
return true
}
return false
}
func IsServerOverloaded(data string) bool {
if strings.Contains(data, `data: {"id": "", "role": "assistant", "content": "Server overloaded, please try again later.", "action": null, "recommend_actions": null, "is_prompt": false, "render_template": null, "session_state": null, "message_type": null, "type": "message_result"}`) {
return true
}
return false
}
func IsFreeLimit(data string) bool {
if strings.Contains(data, `data: {"id": "", "role": "assistant", "content": "You've reached your free usage limit today", "action": {"type": "ACTION_QUOTA_EXCEEDED", "query_string": null, "update_flow_data": null, "label": null, "user_s_input": null, "action_params": null}, "recommend_actions": null, "is_prompt": true, "render_template": null, "session_state": {"consume_usage_quota_exceeded": true}, "message_type": null, "type": "message_result"}`) {
return true
}
return false
}
func IsServiceUnavailablePage(data string) bool {
// 检查基本的 HTML 结构
htmlPattern := `^<!doctype html><html.*?><head>.*?</head><body.*?>.*?</body></html>`
// 检查 Service Unavailable 页面特征
suPatterns := []string{
`<title>Genspark</title>`, // 标题特征
`Service\s+Unavailable`, // 错误信息
`class="bb".*?class="s1".*?class="s2".*?class="s3"`, // 特征性类名结构
`genspark_logo\.png`, // Logo 图片
`gensparkpublicblob-cdn.*?\.azurefd\.net`, // CDN 域名
`<div class="tt">Service Unavailable</div>`, // 错误信息容器
}
// 首先检查整体 HTML 结构
matched, _ := regexp.MatchString(htmlPattern, strings.TrimSpace(data))
if !matched {
return false
}
// 检查特征模式,至少匹配其中的 3 个才认为是目标页面
matchCount := 0
for _, pattern := range suPatterns {
if matched, _ := regexp.MatchString(pattern, data); matched {
matchCount++
}
}
return matchCount >= 3
}
//<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Genspark</title><link rel="icon" href="https://gensparkpublicblob-cdn-e6g4btgjavb5a7gh.z03.azurefd.net/user-upload-image/manual/favicon.ico"><style>body,html{margin:0;padding:0;font-family:Arial}.bb{width:100vw;height:100vh;position:absolute;overflow:hidden}.logo img{margin:20px 0 0 24px;height:24px}.iw{display:flex;flex-direction:column;height:100vh;width:100%}.s1{position:absolute;top:0;left:0;margin-top:-5%;margin-left:15%;width:289px;height:289px;border-radius:289px;opacity:.6;background:radial-gradient(55.64% 49.84%,#2c10d6 0,rgba(44,16,214,.36) 100%);filter:blur(120px)}.s2{position:absolute;top:0;left:0;margin-top:10%;margin-left:50%;width:204.845px;height:204.845px;transform:rotate(-131.346deg);flex-shrink:0;background:radial-gradient(55.64% 49.84%,#7fd1ff 0,rgba(44,16,214,.36) 100%);filter:blur(120px)}.s3{position:absolute;bottom:0;right:0;margin-bottom:10%;margin-right:10%;width:251px;height:251px;border-radius:289.093px;background:radial-gradient(88.27% 88.27% at 90.98% 61.04%,#ce7fff 0,#ffe4af 100%);filter:blur(120px)}.cc{display:flex;justify-content:center;align-items:center;height:100%;width:100%}.hh{align-items:center;display:flex;width:100vw}.dd{margin-top:-200px}.tt{color:#000;text-align:center;font-size:40px;font-style:normal;font-weight:700}@media (max-width:800px){.tt{font-size:30px}}</style></head><body><div class="bb"><div class="s1"></div><div class="s2"></div><div class="s3"></div></div><div class="iw"><div class="hh"><div class="logo"><img src="https://gensparkpublicblob-cdn-e6g4btgjavb5a7gh.z03.azurefd.net/user-upload-image/manual/genspark_logo.png" alt="logo"></div></div><div class="cc"><div class="dd"><div class="tt">Service Unavailable</div></div></div></div></body></html>
//<!doctype html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Genspark</title><link rel="icon" href="https://gensparkpublicblob-cdn-e6g4btgjavb5a7gh.z03.azurefd.net/user-upload-image/manual/favicon.ico"><style>body,html{margin:0;padding:0;font-family:Arial}.bb{width:100vw;height:100vh;position:absolute;overflow:hidden}.logo img{margin:20px 0 0 24px;height:24px}.iw{display:flex;flex-direction:column;height:100vh;width:100%!}(MISSING).s1{position:absolute;top:0;left:0;margin-top:-5%!;(MISSING)margin-left:15%!;(MISSING)width:289px;height:289px;border-radius:289px;opacity:.6;background:radial-gradient(55.64%,#2c10d6 0,rgba(44,16,214,.36) 100%!)(MISSING);filter:blur(120px)}.s2{position:absolute;top:0;left:0;margin-top:10%!;(MISSING)margin-left:50%!;(MISSING)width:204.845px;height:204.845px;transform:rotate(-131.346deg);flex-shrink:0;background:radial-gradient(55.64%,#7fd1ff 0,rgba(44,16,214,.36) 100%!)(MISSING);filter:blur(120px)}.s3{position:absolute;bottom:0;right:0;margin-bottom:10%!;(MISSING)margin-right:10%!;(MISSING)width:251px;height:251px;border-radius:289.093px;background:radial-gradient(88.27% at 90.98%,#ce7fff 0,#ffe4af 100%!)(MISSING);filter:blur(120px)}.cc{display:flex;justify-content:center;align-items:center;height:100%!;(MISSING)width:100%!}(MISSING).hh{align-items:center;display:flex;width:100vw}.dd{margin-top:-200px}.tt{color:#000;text-align:center;font-size:40px;font-style:normal;font-weight:700}@media (max-width:800px){.tt{font-size:30px}}</style></head><body><div class="bb"><div class="s1"></div><div class="s2"></div><div class="s3"></div></div><div class="iw"><div class="hh"><div class="logo"><img src="https://gensparkpublicblob-cdn-e6g4btgjavb5a7gh.z03.azurefd.net/user-upload-image/manual/genspark_logo.png" alt="logo"></div></div><div class="cc"><div class="dd"><div class="tt">Service Unavailable</div></div></div></div></body></html>