Full Go backend + Vue 3 frontend, OpenAI-compatible API, multi-provider account pools, billing/admin, Docker one-command deploy with auto HTTPS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
183 lines
4.7 KiB
Go
183 lines
4.7 KiB
Go
package chatgpt
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"math/rand"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type orderedMap struct {
|
|
keys []string
|
|
values map[string]any
|
|
}
|
|
|
|
func newOrderedMap() *orderedMap {
|
|
return &orderedMap{values: map[string]any{}}
|
|
}
|
|
|
|
func (m *orderedMap) add(key string, value any) {
|
|
if _, ok := m.values[key]; !ok {
|
|
m.keys = append(m.keys, key)
|
|
}
|
|
m.values[key] = value
|
|
}
|
|
|
|
func solveTurnstileToken(dx, p string) string {
|
|
decoded, err := base64.StdEncoding.DecodeString(dx)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
var tokenList [][]any
|
|
if err := json.Unmarshal([]byte(xorString(string(decoded), p)), &tokenList); err != nil {
|
|
return ""
|
|
}
|
|
|
|
processMap := map[int]any{16: p}
|
|
start := time.Now()
|
|
result := ""
|
|
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
toStr := func(value any) string {
|
|
if value == nil {
|
|
return "undefined"
|
|
}
|
|
if s, ok := value.(string); ok {
|
|
special := map[string]string{
|
|
"window.Math": "[object Math]",
|
|
"window.Reflect": "[object Reflect]",
|
|
"window.performance": "[object Performance]",
|
|
"window.localStorage": "[object Storage]",
|
|
"window.Object": "function Object() { [native code] }",
|
|
"window.Reflect.set": "function set() { [native code] }",
|
|
"window.performance.now": "function () { [native code] }",
|
|
"window.Object.create": "function create() { [native code] }",
|
|
"window.Object.keys": "function keys() { [native code] }",
|
|
"window.Math.random": "function random() { [native code] }",
|
|
}
|
|
if specialValue, ok := special[s]; ok {
|
|
return specialValue
|
|
}
|
|
return s
|
|
}
|
|
if list, ok := value.([]string); ok {
|
|
return strings.Join(list, ",")
|
|
}
|
|
return stringValue(value)
|
|
}
|
|
|
|
for _, token := range tokenList {
|
|
if len(token) == 0 {
|
|
continue
|
|
}
|
|
op := intValue(token[0])
|
|
switch op {
|
|
case 2:
|
|
if len(token) >= 3 {
|
|
processMap[intValue(token[1])] = token[2]
|
|
}
|
|
case 3:
|
|
if len(token) >= 2 {
|
|
result = base64.StdEncoding.EncodeToString([]byte(toStr(processMap[intValue(token[1])])))
|
|
}
|
|
case 5:
|
|
if len(token) >= 3 {
|
|
e := intValue(token[1])
|
|
t := intValue(token[2])
|
|
cur := processMap[e]
|
|
inc := processMap[t]
|
|
if list, ok := cur.([]any); ok {
|
|
processMap[e] = append(list, inc)
|
|
} else if _, ok := cur.(string); ok {
|
|
processMap[e] = toStr(cur) + toStr(inc)
|
|
} else {
|
|
processMap[e] = "NaN"
|
|
}
|
|
}
|
|
case 6, 24:
|
|
if len(token) >= 4 {
|
|
e := intValue(token[1])
|
|
t := toStr(processMap[intValue(token[2])])
|
|
n := toStr(processMap[intValue(token[3])])
|
|
v := t + "." + n
|
|
if op == 6 && v == "window.document.location" {
|
|
v = "https://chatgpt.com/"
|
|
}
|
|
processMap[e] = v
|
|
}
|
|
case 8:
|
|
if len(token) >= 3 {
|
|
processMap[intValue(token[1])] = processMap[intValue(token[2])]
|
|
}
|
|
case 14:
|
|
if len(token) >= 3 {
|
|
var parsed any
|
|
if err := json.Unmarshal([]byte(toStr(processMap[intValue(token[2])])), &parsed); err == nil {
|
|
processMap[intValue(token[1])] = parsed
|
|
}
|
|
}
|
|
case 15:
|
|
if len(token) >= 3 {
|
|
b, _ := json.Marshal(processMap[intValue(token[2])])
|
|
processMap[intValue(token[1])] = string(b)
|
|
}
|
|
case 17:
|
|
if len(token) >= 3 {
|
|
e := intValue(token[1])
|
|
target := toStr(processMap[intValue(token[2])])
|
|
switch target {
|
|
case "window.performance.now":
|
|
processMap[e] = float64(time.Since(start).Nanoseconds())/1e6 + rng.Float64()
|
|
case "window.Object.create":
|
|
processMap[e] = newOrderedMap()
|
|
case "window.Object.keys":
|
|
processMap[e] = []string{
|
|
"STATSIG_LOCAL_STORAGE_INTERNAL_STORE_V4",
|
|
"STATSIG_LOCAL_STORAGE_STABLE_ID",
|
|
"client-correlated-secret",
|
|
"oai/apps/capExpiresAt",
|
|
"oai-did",
|
|
"STATSIG_LOCAL_STORAGE_LOGGING_REQUEST",
|
|
"UiState.isNavigationCollapsed.1",
|
|
}
|
|
case "window.Math.random":
|
|
processMap[e] = rng.Float64()
|
|
}
|
|
}
|
|
case 18:
|
|
if len(token) >= 2 {
|
|
raw, err := base64.StdEncoding.DecodeString(toStr(processMap[intValue(token[1])]))
|
|
if err == nil {
|
|
processMap[intValue(token[1])] = string(raw)
|
|
}
|
|
}
|
|
case 19:
|
|
if len(token) >= 2 {
|
|
processMap[intValue(token[1])] = base64.StdEncoding.EncodeToString([]byte(toStr(processMap[intValue(token[1])])))
|
|
}
|
|
case 20:
|
|
if len(token) >= 4 {
|
|
if toStr(processMap[intValue(token[1])]) == toStr(processMap[intValue(token[2])]) {
|
|
if intValue(token[3]) == 3 && len(token) >= 5 {
|
|
result = base64.StdEncoding.EncodeToString([]byte(toStr(processMap[intValue(token[4])])))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func xorString(text, key string) string {
|
|
if key == "" {
|
|
return text
|
|
}
|
|
out := make([]rune, 0, len(text))
|
|
keyRunes := []rune(key)
|
|
for i, ch := range text {
|
|
out = append(out, ch^keyRunes[i%len(keyRunes)])
|
|
}
|
|
return string(out)
|
|
}
|