Initial open-source release (MIT): image2api AI gateway

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>
This commit is contained in:
2026-06-25 22:59:04 +08:00
co-authored by Claude Opus 4.8
commit 606caaf047
142 changed files with 33648 additions and 0 deletions
@@ -0,0 +1,182 @@
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)
}