mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
fix(vkauth): fast-fail on terminal call/link errors (9000/9008, anonymous-only, full)
This commit is contained in:
@@ -257,7 +257,9 @@ func (c *Client) fetch(ctx context.Context, link string, streamID int) (string,
|
||||
lastErr = err
|
||||
c.log.Warnf("[STREAM %d] [VK Auth] Failed with client_id=%s: %v", streamID, creds.ClientID, err)
|
||||
|
||||
if errors.Is(err, ErrCaptchaWaitRequired) || errors.Is(err, ErrFatalCaptchaNoStreams) {
|
||||
if errors.Is(err, ErrCaptchaWaitRequired) || errors.Is(err, ErrFatalCaptchaNoStreams) ||
|
||||
errors.Is(err, ErrInvalidJoinLink) || errors.Is(err, ErrAnonymousBlocked) ||
|
||||
errors.Is(err, ErrCallFull) {
|
||||
return "", "", nil, err
|
||||
}
|
||||
es := err.Error()
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
neturl "net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/samosvalishe/free-turn-proxy/internal/provider/vk/internal/browserprofile"
|
||||
@@ -43,6 +44,10 @@ func (c *Client) fetchCallToken(
|
||||
data = retryData
|
||||
continue
|
||||
}
|
||||
if termErr := classifyLinkError(errObj); termErr != nil {
|
||||
c.log.Errorf("[STREAM %d] [VK Auth] terminal link error: %v", streamID, termErr)
|
||||
return "", termErr
|
||||
}
|
||||
return "", fmt.Errorf("VK API error: %v", errObj)
|
||||
}
|
||||
|
||||
@@ -58,6 +63,39 @@ func (c *Client) fetchCallToken(
|
||||
}
|
||||
}
|
||||
|
||||
// classifyLinkError распознаёт ТЕРМИНАЛЬНЫЕ ответы VK в join-флоу и возвращает
|
||||
// соответствующий sentinel (или nil, если ошибку можно ретраить дальше по
|
||||
// client_id). Терминал = ни client_id, ни captcha не помогут, поэтому fast-fail
|
||||
// вместо бесконечного цикла "решить captcha -> ошибка -> следующий client_id".
|
||||
// Коды VK иногда плавают, поэтому где можно матчим и по тексту error_msg.
|
||||
//
|
||||
// Транзиентные (5 auth-failed, 29/9/6 rate/flood, 14 captcha) сюда НЕ попадают —
|
||||
// их гасить нельзя, иначе можно убить рабочее подключение.
|
||||
func classifyLinkError(errObj map[string]any) error {
|
||||
code := 0
|
||||
if f, ok := errObj["error_code"].(float64); ok {
|
||||
code = int(f)
|
||||
}
|
||||
msg := ""
|
||||
if s, ok := errObj["error_msg"].(string); ok {
|
||||
msg = strings.ToLower(s)
|
||||
}
|
||||
switch {
|
||||
// Битая/мёртвая ссылка: 9008 Join link is not valid, 9000 Call not found.
|
||||
case code == 9000 || code == 9008 ||
|
||||
strings.Contains(msg, "not valid") || strings.Contains(msg, "not found"):
|
||||
return ErrInvalidJoinLink
|
||||
// Звонок живой, но анонимный вход запрещён ("только авторизованные").
|
||||
// Матчим по "anonym" (не по "authoriz" — коллизия с code 5 auth-failed).
|
||||
case strings.Contains(msg, "anonym"):
|
||||
return ErrAnonymousBlocked
|
||||
// Звонок переполнен.
|
||||
case strings.Contains(msg, "full"):
|
||||
return ErrCallFull
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// solveCaptcha выполняет одну попытку решения captcha и возвращает тело POST
|
||||
// для следующего retry или ошибку при исчерпании всех режимов.
|
||||
func (c *Client) solveCaptcha(
|
||||
|
||||
@@ -59,4 +59,19 @@ var (
|
||||
ErrCaptchaWaitRequired = errors.Join(provider.ErrBackoffActive, errors.New("CAPTCHA_WAIT_REQUIRED"))
|
||||
ErrFatalCaptchaNoStreams = errors.Join(provider.ErrFatalNoStreams, errors.New("FATAL_CAPTCHA_FAILED_NO_STREAMS"))
|
||||
ErrLockoutActive = errors.New("global lockout active")
|
||||
|
||||
// Terminal call/link errors: retrying other client_ids or solving the captcha
|
||||
// won't help — only the user changing the link / call settings will. We fast-
|
||||
// fail on these instead of looping "solve captcha -> error -> next credential"
|
||||
// forever, and the joined provider.ErrFatalNoStreams lets the host surface a
|
||||
// specific, actionable message.
|
||||
//
|
||||
// ErrInvalidJoinLink: VK 9008 "Join link is not valid" (broken link) or 9000
|
||||
// "Call not found" (the call ended / no longer exists).
|
||||
ErrInvalidJoinLink = errors.Join(provider.ErrFatalNoStreams, errors.New("INVALID_JOIN_LINK"))
|
||||
// ErrAnonymousBlocked: the call is live but anonymous join is disabled
|
||||
// ("authorized users only") — the user must allow joining by link in VK.
|
||||
ErrAnonymousBlocked = errors.Join(provider.ErrFatalNoStreams, errors.New("ANON_BLOCKED"))
|
||||
// ErrCallFull: the call has reached its participant limit.
|
||||
ErrCallFull = errors.Join(provider.ErrFatalNoStreams, errors.New("CALL_FULL"))
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user