Skip to content

Commit

Permalink
twittermeow: parse response errors
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Dec 2, 2024
1 parent 095b6dd commit 372492d
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 19 deletions.
17 changes: 13 additions & 4 deletions pkg/connector/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,19 @@ func (tc *TwitterClient) Connect(ctx context.Context) {
_, currentUser, err := tc.client.LoadMessagesPage()
if err != nil {
zerolog.Ctx(ctx).Err(err).Msg("Failed to load messages page")
tc.userLogin.BridgeState.Send(status.BridgeState{
StateEvent: status.StateUnknownError,
Error: "twitter-load-error",
})
if twittermeow.IsAuthError(err) {
tc.userLogin.BridgeState.Send(status.BridgeState{
StateEvent: status.StateBadCredentials,
Error: "twitter-invalid-credentials",
Message: err.Error(),
})
} else {
tc.userLogin.BridgeState.Send(status.BridgeState{
StateEvent: status.StateUnknownError,
Error: "twitter-load-error",
Message: err.Error(),
})
}
return
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/twittermeow/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (c *Client) GetCookieString() string {

func (c *Client) Connect() error {
if c.eventHandler == nil {
return ErrConnectPleaseSetEventHandler
return ErrConnectSetEventHandler
}

if !c.isAuthenticated() {
Expand Down
70 changes: 63 additions & 7 deletions pkg/twittermeow/errors.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,72 @@
package twittermeow

import "errors"
import (
"errors"
"fmt"
"strings"
)

var (
// Connection errors
ErrConnectPleaseSetEventHandler = errors.New("please set event handler in client before connecting")
ErrNotAuthenticatedYet = errors.New("client has not been authenticated yet")
ErrConnectSetEventHandler = errors.New("event handler must be set before connecting")
ErrNotAuthenticatedYet = errors.New("client has not been authenticated yet")

// Polling errors
ErrAlreadyPollingUpdates = errors.New("client is already polling for user updates")
ErrNotPollingUpdates = errors.New("client is not polling for user updates")
)

type TwitterError struct {
Message string `json:"message"`
Code int `json:"code"`
}

// Api errors
ErrFailedMarkConversationRead = errors.New("failed to mark conversation as read")
var (
ErrCouldNotAuthenticate error = TwitterError{Code: 32}
ErrUserSuspended error = TwitterError{Code: 63}
ErrAccountSuspended error = TwitterError{Code: 63}
ErrAccountTemporarilyLocked error = TwitterError{Code: 326}
)

func IsAuthError(err error) bool {
return errors.Is(err, ErrCouldNotAuthenticate) ||
errors.Is(err, ErrUserSuspended) ||
errors.Is(err, ErrAccountSuspended) ||
errors.Is(err, ErrAccountTemporarilyLocked)
}

func (te TwitterError) Is(other error) bool {
var ote *TwitterError
if errors.As(other, &ote) {
return te.Code == ote.Code || te.Message == ote.Message
}
return false
}

func (te TwitterError) Error() string {
return fmt.Sprintf("%d: %s", te.Code, te.Message)
}

type TwitterErrors struct {
Errors []TwitterError `json:"errors"`
}

func (te *TwitterErrors) Error() string {
if te == nil || len(te.Errors) == 0 {
return "no errors"
} else if len(te.Errors) == 1 {
return te.Errors[0].Error()
} else {
errs := make([]string, len(te.Errors))
for i, e := range te.Errors {
errs[i] = e.Error()
}
return strings.Join(errs, ", ")
}
}

func (te *TwitterErrors) Unwrap() []error {
errs := make([]error, len(te.Errors))
for i, e := range te.Errors {
errs[i] = e
}
return errs
}
6 changes: 5 additions & 1 deletion pkg/twittermeow/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package twittermeow

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -108,7 +109,10 @@ func (c *Client) makeRequestDirect(url string, method string, headers http.Heade
return nil, nil, fmt.Errorf("%w: %w", ErrResponseReadFailed, err)
}
if response.StatusCode >= 400 {
if len(responseBody) < 512 {
var respErr TwitterErrors
if json.Unmarshal(responseBody, &respErr) == nil {
return response, responseBody, fmt.Errorf("HTTP %d: %w", response.StatusCode, &respErr)
} else if len(responseBody) < 512 {
return response, responseBody, fmt.Errorf("HTTP %d: %s", response.StatusCode, responseBody)
}
return response, responseBody, fmt.Errorf("HTTP %d (%d bytes of data)", response.StatusCode, len(responseBody))
Expand Down
7 changes: 1 addition & 6 deletions pkg/twittermeow/messaging.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,11 @@ func (c *Client) MarkConversationRead(params *payload.MarkConversationReadQuery)
Body: encodedQueryBody,
ContentType: types.FORM,
}
resp, respBody, err := c.makeAPIRequest(apiRequestOpts)
_, _, err = c.makeAPIRequest(apiRequestOpts)
if err != nil {
return err
}

if resp.StatusCode > 204 {
c.Logger.Warn().Any("response_body", string(respBody)).Any("status_code", resp.StatusCode).Any("params", params).Msg("Failed to mark conversation as read")
return ErrFailedMarkConversationRead
}

return nil
}

Expand Down

0 comments on commit 372492d

Please sign in to comment.