Fix: улучшена фильтрация не-отелей, поддержка PDF-политики, исправлены ошибки DNS

This commit is contained in:
neo committed 2026-06-10 00:11:30 +05:00
1 parent 928637ad25
commit 7fb417dad5
10 files changed
+240 -42

No files matched your search

+1 -1
View File
@@ -97,7 +97,7 @@ class FormCheckboxCheck(BaseCheck):
details={
"total_forms": forms_needing_consent,
"without_consent": forms_without_consent,
"sample_texts": [f["checkboxes"][0] for f in forms_without_consent[:3]],
"sample_texts": [f["checkboxes"][0] if f["checkboxes"] else "без чекбоксов" for f in forms_without_consent[:3]],
},
)
+16
View File
@@ -63,6 +63,22 @@ class PrivacyLinkCheck(BaseCheck):
# Проверяем, что ссылка ведет на рабочую страницу
policy_url = found_links[0]["url"]
try:
# Проверяем, не является ли URL документом (PDF, DOCX, XLSX)
doc_extensions = ['.pdf', '.docx', '.doc', '.xlsx', '.xls', '.rtf', '.txt']
is_document = any(policy_url.lower().endswith(ext) for ext in doc_extensions)
if is_document:
# Документ для скачивания — это допустимо для политики
return self._pass_result(
message=f"Найдена ссылка на Политику конфиденциальности ({policy_url})",
details={
"policy_url": policy_url,
"link_text": found_links[0]["text"],
"is_document": True,
},
)
# Для HTML-страниц — проверяем доступность
await page.goto(policy_url, timeout=5000)
policy_text = await page.evaluate("() => document.body.innerText")
await page.goto(url, timeout=5000) # Возвращаемся на главную
+20 -40
View File
@@ -5,6 +5,9 @@
"""
from __future__ import annotations
import socket
from urllib.parse import urlparse
from playwright.async_api import Page
from scanner.checks.base import BaseCheck
@@ -20,65 +23,43 @@ class ServerLocationCheck(BaseCheck):
risk_on_fail = RiskLevel.CRITICAL
default_weight = 25
# Популярные иностранные провайдеры (можно расширять)
# Популярные русские DNS-серверы/хостеры
RUSSIAN_HOSTERS = [
"yandex", "mail.ru", "vk", "selectel", "timeweb", "beget",
"reg.ru", "nic.ru", "rtcdn", "astra", "sbercloud",
"cloud4russia", "гостех", "ростелеком", "мтс", "билайн",
"мегафон", "вымпелком", "ростелеком", "netology",
"мегафон", "вымпелком", "netology",
"yandex.net", "mail.ru", "vk.com", "selectel.cloud",
]
async def check(self, page: Page, url: str) -> CheckResult:
try:
# Получаем IP-адрес сервера через JavaScript
ip_info = await page.evaluate("""() => {
return new Promise((resolve) => {
// Пробуем определить IP через несколько методов
const methods = [
() => fetch('https://api.ipify.org?format=json')
.then(r => r.json()).then(d => ({ip: d.ip, method: 'ipify'})),
() => fetch('https://api.my-ip.io/v2/json')
.then(r => r.json()).then(d => ({ip: d.ip, method: 'my-ip-io'})),
];
# Извлекаем домен из URL
parsed = urlparse(url)
hostname = parsed.hostname or ""
if not hostname:
return self._skip_result(message="Не удалось извлечь домен из URL.")
// Пробуем каждый метод
(async () => {
for (const method of methods) {
try {
const result = await method();
resolve(result);
return;
} catch (e) {}
}
resolve(null);
})();
});
}""")
# Получаем IP через DNS
try:
ip = socket.gethostbyname(hostname)
except socket.gaierror:
return self._skip_result(message=f"Не удалось разрешить DNS для {hostname}.")
if not ip_info:
return self._skip_result(
message="Не удалось определить IP-адрес сервера.",
)
ip = ip_info.get("ip", "")
method = ip_info.get("method", "")
# Определяем страну по IP (используем публичный API)
# Определяем страну по IP
country = await self._get_country(ip)
if not country:
return self._skip_result(
message=f"Не удалось определить страну для IP {ip}.",
)
return self._skip_result(message=f"Не удалось определить страну для IP {ip}.")
# Проверяем, Россия ли это
if country.lower() == "ru" or "Россия" in country:
if country.lower() == "ru" or "Россия" in country or "russia" in country.lower():
return self._pass_result(
message=f"Сервер находится в России (IP: {ip}, Страна: {country})",
details={
"ip": ip,
"country": country,
"method": method,
},
)
@@ -91,7 +72,6 @@ class ServerLocationCheck(BaseCheck):
details={
"ip": ip,
"country": country,
"method": method,
},
)