Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge #8

Merged
merged 22 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Usage for OpenAI
import (
"fmt"

"github.com/acheong08/funcaptcha"
"github.com/xqdoo00o/funcaptcha"
)

func main() {
token, _, _ := funcaptcha.GetOpenAIToken()
token, _ := funcaptcha.GetOpenAIToken("", "")
fmt.Println(token)
}
```
Expand Down
245 changes: 161 additions & 84 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,65 @@ import (
"math/rand"
"net/url"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"

http "github.com/bogdanfinn/fhttp"
tls_client "github.com/bogdanfinn/tls-client"
"github.com/bogdanfinn/tls-client/profiles"
)

var initVer, initHex, arkURL, arkBx string
var arkHeader http.Header
var arkBody url.Values
const arkPreURL = "https://tcr9i.chat.openai.com/fc/gt2/"

var arkURLIns, _ = url.Parse(arkPreURL)

var initVer, initHex string

type arkReq struct {
arkURL string
arkBx string
arkHeader http.Header
arkBody url.Values
arkCookies []*http.Cookie
userAgent string
}

var (
jar = tls_client.NewCookieJar()
options = []tls_client.HttpClientOption{
tls_client.WithTimeoutSeconds(360),
tls_client.WithClientProfile(tls_client.Chrome_112),
tls_client.WithClientProfile(profiles.Chrome_117),
tls_client.WithRandomTLSExtensionOrder(),
tls_client.WithNotFollowRedirects(),
tls_client.WithCookieJar(jar),
}
client *tls_client.HttpClient
proxy = os.Getenv("http_proxy")
client *tls_client.HttpClient
proxy = os.Getenv("http_proxy")
authArks []*arkReq
chat3Arks []*arkReq
chat4Arks []*arkReq
)

type kvPair struct {
Name string `json:"name"`
Value string `json:"value"`
}
type cookie struct {
Name string `json:"name"`
Value string `json:"value"`
Expires string `json:"expires"`
}
type postBody struct {
Params []kvPair `json:"params"`
}
type request struct {
URL string `json:"url"`
Headers []kvPair `json:"headers,omitempty"`
PostData postBody `json:"postData,omitempty"`
Cookies []cookie `json:"cookies,omitempty"`
}
type entry struct {
StartedDateTime string `json:"startedDateTime"`
Expand All @@ -57,59 +80,102 @@ type HARData struct {
}

func readHAR() {
file, err := os.ReadFile("chat.openai.com.har")
if err != nil {
fmt.Println(err)
return
}
var harFile HARData
err = json.Unmarshal(file, &harFile)
if err != nil {
println("Error: not a HAR file!")
return
}
var arkReq entry
for _, v := range harFile.Log.Entries {
if strings.HasPrefix(v.Request.URL, "https://tcr9i.chat.openai.com/fc/gt2/") {
arkReq = v
arkURL = v.Request.URL
break
// 指定需要读取的文件夹路径
dirPath := "./harPool"
var harPath []string
// 打开文件夹并读取其内容
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
}
if arkReq.StartedDateTime == "" {
println("Error: no arkose request!")
return
}
t, err := time.Parse(time.RFC3339, arkReq.StartedDateTime)
if err != nil {
panic(err)
}
bw := getBw(t.Unix())
arkHeader = make(http.Header)
for _, h := range arkReq.Request.Headers {
// arkHeader except cookie & content-length
if !strings.EqualFold(h.Name, "content-length") && !strings.EqualFold(h.Name, "cookie") && !strings.HasPrefix(h.Name, ":") {
arkHeader.Set(h.Name, h.Value)
if strings.EqualFold(h.Name, "user-agent") {
bv = h.Value
// 判断是否为普通文件(非文件夹)
if !info.IsDir() {
// 获取文件后缀名
ext := filepath.Ext(info.Name())
if ext == ".har" {
harPath = append(harPath, path)
}
}
return nil
})
if err != nil {
println("Error: please put HAR files in harPool directory!")
}
arkBody = make(url.Values)
for _, p := range arkReq.Request.PostData.Params {
// arkBody except bda & rnd
if p.Name == "bda" {
cipher, err := url.QueryUnescape(p.Value)
if err != nil {
panic(err)
}
arkBx = Decrypt(cipher, bv+bw)
} else if p.Name != "rnd" {
query, err := url.QueryUnescape(p.Value)
if err != nil {
panic(err)
for _, path := range harPath {
file, err := os.ReadFile(path)
if err != nil {
return
}
var harFile HARData
err = json.Unmarshal(file, &harFile)
if err != nil {
println("Error: not a HAR file!")
return
}
for _, v := range harFile.Log.Entries {
if strings.HasPrefix(v.Request.URL, arkPreURL) {
var tmpArk arkReq
tmpArk.arkURL = v.Request.URL
if v.StartedDateTime == "" {
println("Error: no arkose request!")
continue
}
t, _ := time.Parse(time.RFC3339, v.StartedDateTime)
bw := getBw(t.Unix())
fallbackBw := getBw(t.Unix() - 21600)
tmpArk.arkHeader = make(http.Header)
for _, h := range v.Request.Headers {
// arkHeader except cookie & content-length
if !strings.EqualFold(h.Name, "content-length") && !strings.EqualFold(h.Name, "cookie") && !strings.HasPrefix(h.Name, ":") {
tmpArk.arkHeader.Set(h.Name, h.Value)
if strings.EqualFold(h.Name, "user-agent") {
tmpArk.userAgent = h.Value
}
}
}
tmpArk.arkCookies = []*http.Cookie{}
for _, cookie := range v.Request.Cookies {
expire, _ := time.Parse(time.RFC3339, cookie.Expires)
if expire.After(time.Now()) {
tmpArk.arkCookies = append(tmpArk.arkCookies, &http.Cookie{Name: cookie.Name, Value: cookie.Value, Expires: expire.UTC()})
}
}
var arkType string
tmpArk.arkBody = make(url.Values)
for _, p := range v.Request.PostData.Params {
// arkBody except bda & rnd
if p.Name == "bda" {
cipher, err := url.QueryUnescape(p.Value)
if err != nil {
panic(err)
}
tmpArk.arkBx = Decrypt(cipher, tmpArk.userAgent+bw, tmpArk.userAgent+fallbackBw)
} else if p.Name != "rnd" {
query, err := url.QueryUnescape(p.Value)
if err != nil {
panic(err)
}
tmpArk.arkBody.Set(p.Name, query)
if p.Name == "public_key" {
if query == "0A1D34FC-659D-4E23-B17B-694DCFCF6A6C" {
arkType = "auth"
authArks = append(authArks, &tmpArk)
} else if query == "3D86FBBA-9D22-402A-B512-3420086BA6CC" {
arkType = "chat3"
chat3Arks = append(chat3Arks, &tmpArk)
} else if query == "35536E1E-65B4-4D96-9D97-6ADB7EFF8147" {
arkType = "chat4"
chat4Arks = append(chat4Arks, &tmpArk)
}
}
}
}
if tmpArk.arkBx != "" {
println("success read " + arkType + " arkose")
} else {
println("failed to decrypt HAR file")
}
}
arkBody.Set(p.Name, query)
}
}
}
Expand All @@ -126,50 +192,61 @@ func init() {
}
}

//goland:noinspection GoUnhandledErrorResult
func init() {
cli, _ := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
client = &cli
proxy := os.Getenv("http_proxy")
if proxy != "" {
(*client).SetProxy(proxy)
}
}

//goland:noinspection GoUnusedExportedFunction
func SetTLSClient(cli *tls_client.HttpClient) {
client = cli
}

func GetOpenAIToken(puid string, proxy string) (string, string, error) {
token, err := sendRequest("", puid, proxy)
return token, initHex, err
func GetOpenAIAuthToken(puid string, proxy string) (string, error) {
token, err := sendRequest(0, "", puid, proxy)
return token, err
}

func GetOpenAITokenWithBx(bx string, puid string, proxy string) (string, string, error) {
token, err := sendRequest(getBdaWitBx(bx), puid, proxy)
return token, initHex, err
func GetOpenAIAuthTokenWithBx(bx string, puid string, proxy string) (string, error) {
token, err := sendRequest(0, getBdaWitBx(bx), puid, proxy)
return token, err
}

func GetOpenAIToken(version int, puid string, proxy string) (string, error) {
token, err := sendRequest(version, "", puid, proxy)
return token, err
}

func GetOpenAITokenWithBx(version int, bx string, puid string, proxy string) (string, error) {
token, err := sendRequest(version, getBdaWitBx(bx), puid, proxy)
return token, err
}

//goland:noinspection SpellCheckingInspection,GoUnhandledErrorResult
func sendRequest(bda string, puid string, proxy string) (string, error) {
if arkBx == "" || len(arkBody) == 0 || len(arkHeader) == 0 {
return "", errors.New("a valid HAR file required")
func sendRequest(arkType int, bda string, puid string, proxy string) (string, error) {
var tmpArk *arkReq
if arkType == 0 {
tmpArk = authArks[0]
authArks = append(authArks[1:], authArks[0])
} else if arkType == 3 {
tmpArk = chat3Arks[0]
chat3Arks = append(chat3Arks[1:], chat3Arks[0])
} else {
tmpArk = chat4Arks[0]
chat4Arks = append(chat4Arks[1:], chat4Arks[0])
}
if puid == "" {
return "", errors.New("a valid PUID required")
if tmpArk == nil || tmpArk.arkBx == "" || len(tmpArk.arkBody) == 0 || len(tmpArk.arkHeader) == 0 {
return "", errors.New("a valid HAR file required")
}
if proxy != "" {
(*client).SetProxy(proxy)
}
if bda == "" {
bda = getBDA()
bda = getBDA(tmpArk)
}
tmpArk.arkBody.Set("bda", base64.StdEncoding.EncodeToString([]byte(bda)))
tmpArk.arkBody.Set("rnd", strconv.FormatFloat(rand.Float64(), 'f', -1, 64))
req, _ := http.NewRequest(http.MethodPost, tmpArk.arkURL, strings.NewReader(tmpArk.arkBody.Encode()))
req.Header = tmpArk.arkHeader.Clone()
(*client).GetCookieJar().SetCookies(arkURLIns, tmpArk.arkCookies)
if puid != "" {
req.Header.Set("cookie", "_puid="+puid+";")
}
arkBody.Set("bda", base64.StdEncoding.EncodeToString([]byte(bda)))
arkBody.Set("rnd", strconv.FormatFloat(rand.Float64(), 'f', -1, 64))
req, _ := http.NewRequest(http.MethodPost, arkURL, strings.NewReader(arkBody.Encode()))
req.Header = arkHeader.Clone()
req.Header.Set("cookie", "_puid="+puid+";")
resp, err := (*client).Do(req)
if err != nil {
return "", err
Expand All @@ -196,8 +273,8 @@ func sendRequest(bda string, puid string, proxy string) (string, error) {
}

//goland:noinspection SpellCheckingInspection
func getBDA() string {
bx := arkBx
func getBDA(arkReq *arkReq) string {
var bx string = arkReq.arkBx
if bx == "" {
bx = fmt.Sprintf(bx_template,
getF(),
Expand Down Expand Up @@ -233,7 +310,7 @@ func getBDA() string {
}
bt := getBt()
bw := getBw(bt)
return Encrypt(bx, bv+bw)
return Encrypt(bx, arkReq.userAgent+bw)
}

func getBt() int64 {
Expand Down
Loading