This repository has been archived by the owner on Mar 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chat.go
122 lines (115 loc) · 2.8 KB
/
chat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package chatgpt
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/chromedp/cdproto/runtime"
"github.com/chromedp/chromedp"
"github.com/satori/go.uuid"
)
type Chat struct {
browser *Browser
session *Session
cid uuid.UUID
pid uuid.UUID
}
func (ctx *Chat) Check() error {
if err := ctx.session.CheckAccessToken(); err != nil {
return err
}
if err := ctx.session.CheckClearance(); err != nil {
return err
}
return nil
}
func (ctx *Chat) sendRequest(accessToken string, body []byte, response any) chromedp.EmulateAction {
return chromedp.ActionFunc(func(ctx context.Context) error {
return chromedp.EvaluateAsDevTools(fmt.Sprintf(`new Promise((resolve) => {
fetch("https://chat.openai.com/backend-api/conversation", {
"headers": {
"authorization": "Bearer %s",
"content-type": "application/json",
"x-openai-assistant-app-id": ""
},
"body": JSON.stringify(%s),
"method": "POST",
"mode": "cors",
"credentials": "include"
})
.then(context => context.text())
.then(content => {
let arr = content.split("\n\n");
let len = arr.length;
let index=len-3;
if(index > -1 && index < len){
content = arr[index];
arr = content.split("data: ");
if(arr.length > 1){
resolve(JSON.parse(arr[1]));
return;
}
}
resolve(content);
})
.catch(e => resolve(e.toString()));
})`, accessToken, string(body)), &response, func(p *runtime.EvaluateParams) *runtime.EvaluateParams {
return p.WithAwaitPromise(true)
}).Do(ctx)
})
}
func (ctx *Chat) Send(word string) (*Response, error) {
var (
cid *uuid.UUID
pid *uuid.UUID
)
if ctx.cid != uuid.Nil {
cid = &ctx.cid
}
if ctx.pid == uuid.Nil {
tid := uuid.NewV4()
pid = &tid
} else {
pid = &ctx.pid
}
res, err := ctx.SendMessage(word, cid, pid)
if err != nil {
return nil, err
}
ctx.cid = res.ConversationId
ctx.pid = res.Message.ID
return res, nil
}
func (ctx *Chat) SendMessage(word string, cid, pid *uuid.UUID) (*Response, error) {
var (
chatResponse *Response
response any
)
if err := ctx.Check(); err != nil {
return nil, err
}
chatRequest := NewRequest(word, cid, pid)
requestBytes, err := json.Marshal(chatRequest)
if err != nil {
return nil, err
}
if err = chromedp.Run(ctx.browser.Context,
ctx.sendRequest(ctx.session.AccessToken, requestBytes, &response),
); err != nil {
return nil, err
}
switch res := response.(type) {
case string:
return nil, errors.New(res)
case map[string]any:
if err = ConvertMapToStruct(res, &chatResponse); err != nil {
return nil, errors.New("ConvertMapToStruct failed: " + err.Error())
}
return chatResponse, nil
default:
return nil, errors.New("unknown error")
}
}
func NewChat(browser *Browser, session *Session) *Chat {
return &Chat{browser: browser, session: session}
}