-
-
Notifications
You must be signed in to change notification settings - Fork 57
/
session.go
159 lines (129 loc) · 4.2 KB
/
session.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package session
import (
"errors"
"fmt"
"log"
"sync"
"time"
"github.com/m1guelpf/chatgpt-discord/src/ref"
"github.com/playwright-community/playwright-go"
)
func GetSession() (string, error) {
runOptions := playwright.RunOptions{
Browsers: []string{"chromium"},
Verbose: false,
}
err := playwright.Install(&runOptions)
if err != nil {
return "", errors.New(fmt.Sprintf("Couldn't install headless browser: %v", err))
}
pw, err := playwright.Run(&runOptions)
if err != nil {
return "", errors.New(fmt.Sprintf("Couldn't start headless browser: %v", err))
}
browser, page, err := launchBrowser(pw, "https://chat.openai.com", true)
if err != nil {
return "", errors.New(fmt.Sprintf("Couldn't launch headless browser: %v", err))
}
for page.URL() != "https://chat.openai.com/chat" {
result := <-logIn(pw)
if result.Error != nil {
return "", errors.New(fmt.Sprintf("Couldn't log in: %v", result.Error))
}
authCookie := playwright.BrowserContextAddCookiesOptionsCookies{
Path: ref.Of("/"),
Secure: ref.Of(true),
HttpOnly: ref.Of(true),
Value: ref.Of(result.SessionToken),
Domain: ref.Of("chat.openai.com"),
SameSite: playwright.SameSiteAttributeLax,
Name: ref.Of("__Secure-next-auth.session-token"),
Expires: ref.Of(float64(time.Now().AddDate(0, 1, 0).Unix())),
}
if err := browser.AddCookies(authCookie); err != nil {
return "", errors.New(fmt.Sprintf("Couldn't save session to browser: %v", err))
}
if _, err = page.Goto("https://chat.openai.com/chat"); err != nil {
return "", errors.New(fmt.Sprintf("Couldn't reload page: %v", err))
}
}
sessionToken, err := getSessionCookie(browser)
if err != nil {
return "", errors.New(fmt.Sprintf("Couldn't get session token: %v", err))
}
if err := browser.Close(); err != nil {
return "", errors.New(fmt.Sprintf("Couldn't close headless browser: %v", err))
}
if err := pw.Stop(); err != nil {
return "", errors.New(fmt.Sprintf("Couldn't stop headless browser: %v", err))
}
return sessionToken, nil
}
func launchBrowser(pw *playwright.Playwright, url string, headless bool) (playwright.BrowserContext, playwright.Page, error) {
browser, err := pw.Chromium.LaunchPersistentContext("/tmp/chatgpt", playwright.BrowserTypeLaunchPersistentContextOptions{Headless: playwright.Bool(headless)})
if err != nil {
return nil, nil, errors.New(fmt.Sprintf("Couldn't launch headless browser: %v", err))
}
page, err := browser.NewPage()
if err != nil {
return nil, nil, errors.New(fmt.Sprintf("Couldn't create a new tab on headless browser: %v", err))
}
if _, err = page.Goto(url); err != nil {
return nil, nil, errors.New(fmt.Sprintf("Couldn't open website: %v", err))
}
return browser, page, nil
}
type Result struct {
Error error
SessionToken string
}
func logIn(pw *playwright.Playwright) <-chan Result {
var lock sync.Mutex
r := make(chan Result)
lock.Lock()
go func() {
defer close(r)
defer lock.Unlock()
browser, page, err := launchBrowser(pw, "https://chat.openai.com/", false)
if err != nil {
r <- Result{Error: errors.New(fmt.Sprintf("Couldn't launch headless browser: %v", err))}
return
}
log.Println("Please log in to OpenAI Chat")
page.On("framenavigated", func(frame playwright.Frame) {
if frame.URL() != "https://chat.openai.com/chat" {
return
}
lock.Unlock()
})
lock.Lock()
sessionToken, err := getSessionCookie(browser)
if err != nil {
r <- Result{Error: errors.New(fmt.Sprintf("Couldn't get session token: %v", err))}
return
}
if err := browser.Close(); err != nil {
r <- Result{Error: errors.New(fmt.Sprintf("Couldn't close headless browser: %v", err))}
return
}
r <- Result{SessionToken: sessionToken}
}()
return r
}
func getSessionCookie(browser playwright.BrowserContext) (string, error) {
cookies, err := browser.Cookies("https://chat.openai.com/")
if err != nil {
return "", errors.New(fmt.Sprintf("Couldn't get cookies: %v", err))
}
var sessionToken string
for _, cookie := range cookies {
if cookie.Name == "__Secure-next-auth.session-token" {
sessionToken = cookie.Value
break
}
}
if sessionToken == "" {
return "", errors.New(fmt.Sprintf("Couldn't get session token"))
}
return sessionToken, nil
}