diff --git a/internal/provider/vk/internal/vkauth/cache.go b/internal/provider/vk/internal/vkauth/cache.go index 6bac239..ba446ae 100644 --- a/internal/provider/vk/internal/vkauth/cache.go +++ b/internal/provider/vk/internal/vkauth/cache.go @@ -2,7 +2,6 @@ package vkauth import ( "errors" - "strings" "sync" "sync/atomic" @@ -88,11 +87,6 @@ func IsAuthError(err error) bool { return false } } - // Ошибки не от TURN-сервера (получение кредов у провайдера) типа не несут. - s := err.Error() - return strings.Contains(s, "401") || - strings.Contains(s, "Unauthorized") || - strings.Contains(s, "authentication") || - strings.Contains(s, "invalid credential") || - strings.Contains(s, "stale nonce") + + return errors.Is(err, ErrVKAuthFailed) } diff --git a/internal/provider/vk/internal/vkauth/client.go b/internal/provider/vk/internal/vkauth/client.go index 8767d69..436022b 100644 --- a/internal/provider/vk/internal/vkauth/client.go +++ b/internal/provider/vk/internal/vkauth/client.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net" - "strings" "sync" "sync/atomic" "time" @@ -280,8 +279,7 @@ func (c *Client) fetch(ctx context.Context, link string, streamID int) (string, errors.Is(err, ErrCallFull) || errors.Is(err, captcha.ErrUnavailable) { return "", "", nil, err } - es := err.Error() - if strings.Contains(es, "error_code:29") || strings.Contains(es, "error_code: 29") || strings.Contains(es, "Rate limit") { + if errors.Is(err, ErrVKRateLimit) { c.log.Warnf("[STREAM %d] [VK Auth] Rate limit detected, trying next credentials", streamID) } } diff --git a/internal/provider/vk/internal/vkauth/client_test.go b/internal/provider/vk/internal/vkauth/client_test.go index 89d53f1..d242180 100644 --- a/internal/provider/vk/internal/vkauth/client_test.go +++ b/internal/provider/vk/internal/vkauth/client_test.go @@ -31,20 +31,17 @@ func newTestClient(t *testing.T, fake tokenChainFn, opts ...func(*Client)) *Clie func TestIsAuthError(t *testing.T) { t.Parallel() - cases := map[string]bool{ - "401 Unauthorized": true, - "alloc failed: 401": true, - "stale nonce": true, - "invalid credential": true, - "authentication required": true, - "connection refused": false, - "dial tcp 10.0.0.1:48612: i/o timeout": false, - "": false, + cases := map[error]bool{ + fmt.Errorf("%w: map[error_code:5]", ErrVKAuthFailed): true, + fmt.Errorf("%w: map[error_code:29]", ErrVKRateLimit): false, + // Порт с "401" внутри не делает сетевую ошибку ошибкой авторизации. + errors.New("dial udp 77.88.8.8:10401: i/o timeout"): false, + errors.New("401 Unauthorized"): false, + errors.New("connection refused"): false, } - for msg, want := range cases { - got := IsAuthError(errors.New(msg)) - if got != want { - t.Errorf("IsAuthError(%q) = %v, want %v", msg, got, want) + for err, want := range cases { + if got := IsAuthError(err); got != want { + t.Errorf("IsAuthError(%v) = %v, want %v", err, got, want) } } if IsAuthError(nil) { diff --git a/internal/provider/vk/internal/vkauth/token_call.go b/internal/provider/vk/internal/vkauth/token_call.go index 2a43c80..a7c0d99 100644 --- a/internal/provider/vk/internal/vkauth/token_call.go +++ b/internal/provider/vk/internal/vkauth/token_call.go @@ -46,6 +46,9 @@ func (c *Client) fetchCallToken( c.log.Errorf("[STREAM %d] [VK Auth] terminal link error: %v", streamID, termErr) return "", termErr } + if sentinel := apiErrSentinel(errObj); sentinel != nil { + return "", fmt.Errorf("%w: %v", sentinel, errObj) + } return "", fmt.Errorf("VK API error: %v", errObj) } @@ -61,11 +64,25 @@ func (c *Client) fetchCallToken( } } -func classifyLinkError(errObj map[string]any) error { - code := 0 +func apiErrCode(errObj map[string]any) int { if f, ok := errObj["error_code"].(float64); ok { - code = int(f) + return int(f) } + return 0 +} + +func apiErrSentinel(errObj map[string]any) error { + switch apiErrCode(errObj) { + case 5: + return ErrVKAuthFailed + case 29: + return ErrVKRateLimit + } + return nil +} + +func classifyLinkError(errObj map[string]any) error { + code := apiErrCode(errObj) if code == 9000 || code == 9008 { return ErrInvalidJoinLink diff --git a/internal/provider/vk/internal/vkauth/types.go b/internal/provider/vk/internal/vkauth/types.go index e414140..8131fd1 100644 --- a/internal/provider/vk/internal/vkauth/types.go +++ b/internal/provider/vk/internal/vkauth/types.go @@ -50,4 +50,6 @@ var ( ErrInvalidJoinLink = errors.Join(provider.ErrFatalNoStreams, errors.New("INVALID_JOIN_LINK")) ErrAnonymousBlocked = errors.Join(provider.ErrFatalNoStreams, errors.New("ANON_BLOCKED")) ErrCallFull = errors.Join(provider.ErrFatalNoStreams, errors.New("CALL_FULL")) + ErrVKAuthFailed = errors.New("VK authorization failed") + ErrVKRateLimit = errors.New("VK rate limit") )