Код примерно следующий:
public void AntigateAuthorize(int appId, string email, string password, Settings settings, string antigateKey)
{
var authorizationCompleted = false;
try
{
Authorize(appId, email, password, settings);
authorizationCompleted = true;
}
catch (CaptchaNeededException exception)
{
var captchaSid = exception.Sid;
var image = GetImageFromUrl(exception.Img.AbsoluteUri);
try
{
const int numberOfAuthorizationRetries = 5;
var retryAuthorizationsCount = numberOfAuthorizationRetries;
do
{
var anticaptcha = new AntiCaptcha(antigateKey);
try
{
var captchaKey = anticaptcha?.GetAnswer(image);
if (captchaKey != null)
{
Authorize(appId, email, password, settings, captchaSid, captchaKey);
authorizationCompleted = true;
}
else
{
Logger.Error("Ответ от сервера Antigate не получен.");
}
}
catch (CaptchaNeededException)
{
Logger.Trace("Капча распознана неверно.");
anticaptcha.FalseCaptcha();
retryAuthorizationsCount--;
if (retryAuthorizationsCount == 0)
{
Logger.Trace("Заданное количество попыток авторизации исчерпано.");
throw;
}
}
} while (!authorizationCompleted && retryAuthorizationsCount > 0);
}
catch (AntigateErrorException aee)
{
Logger.Error("Ошибка Antigate: {0}", aee.Message);
}
}
catch (VkApiAuthorizationException)
{
Logger.Error("Не удалось авторизовать приложение. Неправильный логин или пароль.");
}
catch (VkApiException)
{
Logger.Error("В процессе попытки авторизации произошла неизвестная ошибка.");
}
}
public static Image GetImageFromUrl(string url)
{
using (var stream = ((HttpWebResponse)((HttpWebRequest)WebRequest.Create(url)).GetResponse()).GetResponseStream())
return stream == null ? null : Image.FromStream(stream);
}
Проблема в том, если обрабатывать ошибку CaptchaNeededException однократно, то всё получается, а если в цикле - получается плохо и некрасиво.
Ответ
Можно попробовать разбить на мелкие функции. Например, так:
public void AntigateAuthorize(
int appId, string email, string password,
Settings settings, string antigateKey)
{
try
{
try
{
Authorize(appId, email, password, settings);
}
catch (CaptchaNeededException exception)
{
AuthorizeWithCaptcha(appId, email, password, settings, exception);
}
}
catch (AntigateErrorException)
{
// ?
}
catch (VkApiAuthorizationException)
{
Logger.Error(
"Не удалось авторизовать приложение. Неправильный логин или пароль.");
}
catch (VkApiException)
{
Logger.Error(
"В процессе попытки авторизации произошла неизвестная ошибка.");
}
}
Вспомогательные функции:
private void AuthorizeWithCaptchaOnceImpl(
int appId, string email, string password,
Settings settings, CaptchaNeededException reason,
AntiCaptcha anticaptcha)
{
var captchaSid = reason.Sid;
var image = GetImageFromUrl(reason.Img.AbsoluteUri);
try
{
var captchaKey = anticaptcha.GetAnswer(image);
if (captchaKey == null)
{
Logger.Error("Ответ от сервера Antigate не получен.");
throw new NoAntigateResponceException();
}
Authorize(appId, email, password, settings, captchaSid, captchaKey);
}
catch (CaptchaNeededException)
{
Logger.Trace("Капча распознана неверно.");
anticaptcha.FalseCaptcha();
throw;
}
}
void AuthorizeWithCaptcha(
int appId, string email, string password,
Settings settings, CaptchaNeededException exception)
{
try
{
var anticaptcha = new AntiCaptcha(antigateKey);
const int numberOfAuthorizationRetries = 5;
CaptchaNeededException currentException = exception;
for (int retry = 0; retry < numberOfAuthorizationRetries; retry++)
{
try
{
AuthorizeWithCaptchaOnceImpl(
appId, email, password,
settings, currentException, anticaptcha);
return;
}
catch (CaptchaNeededException ex)
{
currentException = ex;
}
catch (NoAntigateResponceException ex)
{
// nothing to do, just retry
}
}
throw new RetryNumberExceededException();
}
catch (AntigateErrorException aee)
{
Logger.Error("Ошибка Antigate: {0}", aee.Message);
throw;
}
}
Заметьте, что я немного поменял логику. Например, после неудачного распознавания капчи теперь картинка меняется. Также, в результате превышения разрешённого количества попыток распознавания выбрасывается исключение (хотя, возможно, вы захотите вернуть bool из функции).
Комментариев нет:
Отправить комментарий