Browse Source

fix(client): accept smart captcha redirects

pull/162/head
Moroka8 3 weeks ago
parent
commit
e87b50a413
  1. 81
      pkg/clientcore/main.go
  2. 47
      pkg/clientcore/main_test.go

81
pkg/clientcore/main.go

@ -435,48 +435,67 @@ type VkCaptchaError struct {
CaptchaAttempt string
}
func parseVKErrorCode(value interface{}) (int, bool) {
switch v := value.(type) {
case float64:
return int(v), true
case int:
return v, true
case json.Number:
n, err := v.Int64()
return int(n), err == nil
case string:
n, err := strconv.Atoi(v)
return n, err == nil
default:
return 0, false
}
}
func parseVKString(value interface{}) (string, bool) {
switch v := value.(type) {
case string:
return v, v != ""
case float64:
return fmt.Sprintf("%.0f", v), true
case int:
return strconv.Itoa(v), true
case json.Number:
return v.String(), v.String() != ""
default:
return "", false
}
}
func ParseVkCaptchaError(errData map[string]interface{}) *VkCaptchaError {
// Extract error_code
codeFloat, ok := errData["error_code"].(float64)
code, ok := parseVKErrorCode(errData["error_code"])
if !ok {
log.Printf("missing error_code in captcha error data")
return nil
}
code := int(codeFloat)
// Extract redirect_uri
RedirectURI, ok := errData["redirect_uri"].(string)
if !ok {
log.Printf("missing redirect_uri in captcha error data")
return nil
}
// Extract captcha_sid
captchaSid, ok := errData["captcha_sid"].(string)
if !ok {
// try numeric
if sidNum, ok2 := errData["captcha_sid"].(float64); ok2 {
captchaSid = fmt.Sprintf("%.0f", sidNum)
} else {
log.Printf("missing captcha_sid in captcha error data")
return nil
}
captchaSid, _ := parseVKString(errData["captcha_sid"])
if captchaSid == "" {
log.Printf("captcha_sid not present in captcha error data")
}
// Extract captcha_img
captchaImg, ok := errData["captcha_img"].(string)
if !ok {
log.Printf("missing captcha_img in captcha error data")
return nil
captchaImg, _ := parseVKString(errData["captcha_img"])
if captchaImg == "" {
log.Printf("captcha_img not present in captcha error data")
}
// Extract error_msg
errorMsg, ok := errData["error_msg"].(string)
if !ok {
log.Printf("missing error_msg in captcha error data")
return nil
errorMsg, _ := parseVKString(errData["error_msg"])
if errorMsg == "" {
log.Printf("error_msg not present in captcha error data")
}
// Extract redirect_uri
RedirectURI, _ := parseVKString(errData["redirect_uri"])
// Extract session token
var sessionToken string
if RedirectURI != "" {
@ -493,6 +512,14 @@ func ParseVkCaptchaError(errData map[string]interface{}) *VkCaptchaError {
sessionToken = st
}
}
if RedirectURI == "" && captchaImg == "" {
log.Printf("missing redirect_uri and captcha_img in captcha error data")
return nil
}
if RedirectURI != "" && sessionToken == "" {
log.Printf("missing session_token in captcha redirect_uri")
return nil
}
// Extract is_sound_captcha_available
isSound, ok := errData["is_sound_captcha_available"].(bool)
@ -531,7 +558,7 @@ func ParseVkCaptchaError(errData map[string]interface{}) *VkCaptchaError {
}
func (e *VkCaptchaError) IsCaptchaError() bool {
return e.ErrorCode == 14 && e.RedirectURI != "" && e.SessionToken != ""
return e.ErrorCode == 14 && ((e.RedirectURI != "" && e.SessionToken != "") || e.CaptchaImg != "")
}
func solveVkCaptcha(ctx context.Context, captchaErr *VkCaptchaError, streamID int, client tlsclient.HttpClient, profile Profile, useSliderPOC bool) (string, error) {

47
pkg/clientcore/main_test.go

@ -59,3 +59,50 @@ func TestCaptchaSolveModeForAttempt(t *testing.T) {
}
})
}
func TestParseVkCaptchaErrorSupportsSmartCaptchaRedirectOnly(t *testing.T) {
t.Parallel()
captchaErr := ParseVkCaptchaError(map[string]interface{}{
"error_code": float64(14),
"error_msg": "Captcha need",
"is_enabled_captcha": true,
"redirect_uri": "https://id.vk.ru/not_robot_captcha?domain=vk.com&session_token=session-123&variant=popup&blank=1",
})
if captchaErr == nil {
t.Fatal("expected captcha error to parse")
return
}
if !captchaErr.IsCaptchaError() {
t.Fatal("expected parsed error to be recognized as captcha")
}
if captchaErr.SessionToken != "session-123" {
t.Fatalf("expected session token from redirect_uri, got %q", captchaErr.SessionToken)
}
if captchaErr.CaptchaSid != "" {
t.Fatalf("expected missing captcha_sid to stay empty, got %q", captchaErr.CaptchaSid)
}
}
func TestParseVkCaptchaErrorSupportsLegacyImageCaptcha(t *testing.T) {
t.Parallel()
captchaErr := ParseVkCaptchaError(map[string]interface{}{
"error_code": float64(14),
"error_msg": "Captcha need",
"captcha_sid": float64(12345),
"captcha_img": "https://api.vk.ru/captcha.php?sid=12345",
})
if captchaErr == nil {
t.Fatal("expected legacy captcha error to parse")
return
}
if !captchaErr.IsCaptchaError() {
t.Fatal("expected legacy captcha error to be recognized as captcha")
}
if captchaErr.CaptchaSid != "12345" {
t.Fatalf("expected numeric captcha_sid to parse, got %q", captchaErr.CaptchaSid)
}
}

Loading…
Cancel
Save