]> git.giacomolli.uk - onechat/blobdiff - chatgpt.go
Write private data archives with safe extraction
[onechat] / chatgpt.go
index 302e143bb732d029378ce5382f9e519eb8753c8f..8849adaf69c70d511d1075217494a2072cd50006 100644 (file)
@@ -131,6 +131,7 @@ func (a *ChatGPTAuth) Login(ctx context.Context, out io.Writer) error {
        defer a.mutex.Unlock()
 
        var code ChatGPTDeviceCode
+
        err := a.postJSON(ctx, "/api/accounts/deviceauth/usercode", map[string]string{
                "client_id": chatgptClientID,
        }, &code)
@@ -145,7 +146,7 @@ func (a *ChatGPTAuth) Login(ctx context.Context, out io.Writer) error {
 
        _, err = fmt.Fprintf(out, "Open %s/codex/device on any device and enter this code:\n\n    %s\n\nWaiting for the approval...\n", a.issuer, userCode)
        if err != nil {
-               return err
+               return fmt.Errorf("write device code: %w", err)
        }
 
        grant, err := a.poll(ctx, code.DeviceAuthID, userCode, chatgptPollInterval(code.Interval))
@@ -164,8 +165,11 @@ func (a *ChatGPTAuth) Login(ctx context.Context, out io.Writer) error {
        }
 
        _, err = fmt.Fprintln(out, "Logged in.")
+       if err != nil {
+               return fmt.Errorf("write login result: %w", err)
+       }
 
-       return err
+       return nil
 }
 
 // read reads the token file.
@@ -180,6 +184,7 @@ func (a *ChatGPTAuth) read() (ChatGPTTokenFile, error) {
        }
 
        var tokens ChatGPTTokenFile
+
        err = json.Unmarshal(data, &tokens)
        if err == nil && (tokens.AccessToken == "" || tokens.RefreshToken == "" || tokens.AccountID == "") {
                err = errors.New("a token or the account ID is missing")
@@ -196,6 +201,7 @@ func (a *ChatGPTAuth) read() (ChatGPTTokenFile, error) {
 // It keeps the old refresh token and ID token when the answer has none.
 func (a *ChatGPTAuth) refresh(ctx context.Context, tokens ChatGPTTokenFile) (ChatGPTTokenFile, error) {
        var response ChatGPTTokenResponse
+
        err := a.postJSON(ctx, "/oauth/token", map[string]string{
                "client_id":     chatgptClientID,
                "grant_type":    "refresh_token",
@@ -252,6 +258,7 @@ func (a *ChatGPTAuth) poll(ctx context.Context, deviceID, userCode string, inter
 
        for {
                var grant ChatGPTDeviceGrant
+
                status, err := a.post(ctx, "/api/accounts/deviceauth/token", "application/json", body, &grant)
                if err == nil && (grant.AuthorizationCode == "" || grant.CodeVerifier == "") {
                        err = errors.New("device grant has no authorization code or code verifier")
@@ -269,6 +276,7 @@ func (a *ChatGPTAuth) poll(ctx context.Context, deviceID, userCode string, inter
                select {
                case <-ctx.Done():
                        timer.Stop()
+
                        return ChatGPTDeviceGrant{}, fmt.Errorf("wait for approval: %w", ctx.Err())
                case <-timer.C:
                }
@@ -286,6 +294,7 @@ func (a *ChatGPTAuth) exchange(ctx context.Context, grant ChatGPTDeviceGrant) (C
        }
 
        var response ChatGPTTokenResponse
+
        _, err := a.post(ctx, "/oauth/token", "application/x-www-form-urlencoded", []byte(form.Encode()), &response)
        if err != nil {
                return ChatGPTTokenFile{}, fmt.Errorf("exchange code for tokens: %w", err)
@@ -334,6 +343,7 @@ func (a *ChatGPTAuth) post(ctx context.Context, path, contentType string, body [
        }
 
        request.Header.Set("Content-Type", contentType)
+
        response, err := a.http.Do(request)
        if err != nil {
                return 0, fmt.Errorf("send request: %w", err)
@@ -414,6 +424,7 @@ func chatgptPollInterval(raw json.RawMessage) time.Duration {
 // none.
 func chatgptAccountID(token string) string {
        var claims map[string]json.RawMessage
+
        if !chatgptDecodeClaims(token, &claims) {
                return ""
        }