Save all currently accumulated repository changes as a backup snapshot for Gitea so no local work is lost.
172 lines
6.1 KiB
JavaScript
172 lines
6.1 KiB
JavaScript
// JavaScript функция для проверки и ожидания решения капчи на странице поиска
|
||
// Используется в n8n workflow ноде "проверяем капчу"
|
||
// Работает только для региональных судов (*.sudrf.ru)
|
||
|
||
export default async function ({ page, context }) {
|
||
// Получаем данные из переменных n8n workflow
|
||
const searchUrl = '{{ $json.search_url }}' || '{{ $json.url }}';
|
||
|
||
if (!searchUrl) throw new Error('❌ Не передан URL страницы поиска');
|
||
|
||
const sleep = ms => new Promise(r => setTimeout(r, ms));
|
||
|
||
// Определяем тип суда по URL
|
||
const isRegionalCourt = /\.sudrf\.ru/.test(searchUrl) && !/mos-(gorsud|sud)\.ru/.test(searchUrl);
|
||
|
||
if (!isRegionalCourt) {
|
||
return {
|
||
url: searchUrl,
|
||
source: new URL(searchUrl).hostname,
|
||
status: 'error',
|
||
error_type: 'not_regional_court',
|
||
error_message: 'Проверка капчи поддерживается только для региональных судов',
|
||
captcha_present: false,
|
||
captcha_solved: false,
|
||
message: 'Не региональный суд'
|
||
};
|
||
}
|
||
|
||
// Установка заголовков и поведения браузера
|
||
await page.setViewport({ width: 1920, height: 1080 });
|
||
await page.setExtraHTTPHeaders({
|
||
"Referer": "https://sudrf.ru/",
|
||
"Origin": "https://sudrf.ru",
|
||
"Accept-Language": "ru,en;q=0.9",
|
||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||
"Upgrade-Insecure-Requests": "1",
|
||
});
|
||
await page.setUserAgent(
|
||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
|
||
);
|
||
|
||
try {
|
||
// Переходим на страницу поиска (если ещё не на ней)
|
||
const currentUrl = page.url();
|
||
if (currentUrl !== searchUrl) {
|
||
await page.goto(searchUrl, { waitUntil: "domcontentloaded", timeout: 30000 });
|
||
await sleep(1000);
|
||
}
|
||
|
||
// Закрыть баннеры cookies, если есть
|
||
try {
|
||
await page.waitForSelector("#cookie-disclaimer .cd-close-button, .cookie-accept, .cookie__close", { timeout: 2000 });
|
||
const btns = await page.$$("#cookie-disclaimer .cd-close-button, .cookie-accept, .cookie__close");
|
||
if (btns[0]) await btns[0].click();
|
||
} catch (_) {}
|
||
|
||
await sleep(500);
|
||
|
||
// Проверяем наличие капчи
|
||
const checkCaptcha = async () => {
|
||
return await page.evaluate(() => {
|
||
const captchaSelectors = [
|
||
'img[src*="captcha"]',
|
||
'img[src*="recaptcha"]',
|
||
'.captcha',
|
||
'#captcha',
|
||
'iframe[src*="recaptcha"]',
|
||
'div[class*="captcha"]',
|
||
'div[id*="captcha"]'
|
||
];
|
||
return captchaSelectors.some(sel => document.querySelector(sel));
|
||
});
|
||
};
|
||
|
||
const hasCaptcha = await checkCaptcha();
|
||
|
||
if (!hasCaptcha) {
|
||
// Капчи нет - можно продолжать поиск
|
||
return {
|
||
url: searchUrl,
|
||
source: new URL(searchUrl).hostname,
|
||
status: 'success',
|
||
error_type: null,
|
||
error_message: null,
|
||
captcha_present: false,
|
||
captcha_solved: true,
|
||
message: 'Капча не обнаружена, можно продолжать поиск'
|
||
};
|
||
}
|
||
|
||
// Капча обнаружена - ждём её решения
|
||
let captchaSolved = false;
|
||
const maxWaitTime = 30000; // 30 секунд
|
||
const checkInterval = 2000; // Проверяем каждые 2 секунды
|
||
const startTime = Date.now();
|
||
|
||
while (Date.now() - startTime < maxWaitTime) {
|
||
await sleep(checkInterval);
|
||
|
||
// Проверяем, изменилась ли страница (может быть редирект после решения капчи)
|
||
const currentUrl = page.url();
|
||
if (currentUrl !== searchUrl && (currentUrl.includes('name_op=case') || currentUrl.includes('case_id'))) {
|
||
// Если мы уже на странице дела - капча решена и произошёл редирект
|
||
captchaSolved = true;
|
||
return {
|
||
url: searchUrl,
|
||
source: new URL(searchUrl).hostname,
|
||
status: 'success',
|
||
error_type: null,
|
||
error_message: null,
|
||
captcha_present: true,
|
||
captcha_solved: true,
|
||
found_url: currentUrl,
|
||
message: 'Капча решена, произошёл редирект на страницу дела'
|
||
};
|
||
}
|
||
|
||
const stillHasCaptcha = await checkCaptcha();
|
||
if (!stillHasCaptcha) {
|
||
captchaSolved = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!captchaSolved) {
|
||
// Капча всё ещё присутствует
|
||
const finalCheck = await checkCaptcha();
|
||
if (finalCheck) {
|
||
return {
|
||
url: searchUrl,
|
||
source: new URL(searchUrl).hostname,
|
||
status: 'error',
|
||
error_type: 'captcha_required',
|
||
error_message: 'Требуется решение капчи',
|
||
captcha_present: true,
|
||
captcha_solved: false,
|
||
message: 'На странице поиска требуется решение капчи. Ожидание 30 секунд не помогло.'
|
||
};
|
||
}
|
||
}
|
||
|
||
// Капча решена
|
||
return {
|
||
url: searchUrl,
|
||
source: new URL(searchUrl).hostname,
|
||
status: 'success',
|
||
error_type: null,
|
||
error_message: null,
|
||
captcha_present: true,
|
||
captcha_solved: true,
|
||
message: 'Капча решена, можно продолжать поиск'
|
||
};
|
||
|
||
} catch (error) {
|
||
return {
|
||
url: searchUrl,
|
||
source: new URL(searchUrl).hostname,
|
||
status: 'error',
|
||
error_type: 'check_failed',
|
||
error_message: `Ошибка при проверке капчи: ${error.message}`,
|
||
captcha_present: false,
|
||
captcha_solved: false,
|
||
message: `Ошибка: ${error.message}`
|
||
};
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|