fix proxy

This commit is contained in:
Yuriy Yuriev
2026-05-22 01:22:56 +07:00
parent 2a6c1cd633
commit 2f18f4a5a1
3 changed files with 65 additions and 25 deletions
+11 -1
View File
@@ -255,6 +255,14 @@ class BotInterface:
await callback.answer()
# === Перезапуск ===
@dp.callback_query(F.data == "reload_proxies")
async def cb_reload_proxies(callback: CallbackQuery):
if not await require_admin(callback):
return
count = interface.proxy_manager.reload()
await interface._show_status(callback.message, edit=True)
await callback.answer(f"✅ Прокси перезагружены: {count} шт.")
@dp.callback_query(F.data == "bot_restart_confirm")
async def cb_restart_confirm(callback: CallbackQuery):
if not await require_admin(callback):
@@ -1685,6 +1693,7 @@ class BotInterface:
)
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="🔄 Обновить", callback_data="menu_status"))
builder.row(InlineKeyboardButton(text="🔃 Перезагрузить прокси", callback_data="reload_proxies"))
builder.row(InlineKeyboardButton(text="🔁 Перезапустить бота", callback_data="bot_restart_confirm"))
builder.row(InlineKeyboardButton(text="🔙 В меню", callback_data="menu_main"))
await self._edit_or_send(message, text, builder.as_markup(), edit)
@@ -2166,7 +2175,8 @@ class BotInterface:
delay = params.get_delay()
series_size = params.get_series_size()
logger.info(
f"⏳ Next series: {series_size} clicks, "
f"⏳ Next series: {series_size} clicks "
f"(range {params.min_series}-{params.max_series}), "
f"delay {delay}s ({delay//60}m {delay%60}s), "
f"reading {params.min_reading}-{params.max_reading}s, "
f"done {params.successful_visits}/{max_v}"
+38 -18
View File
@@ -69,13 +69,13 @@ class Proxy:
- http://ip:port:login:password
"""
line = line.strip()
# Определяем тип прокси по префиксу
proxy_type = default_type
if "://" in line:
protocol, rest = line.split("://", 1)
protocol = protocol.lower()
if protocol in ["socks5", "socks"]:
proxy_type = ProxyType.SOCKS5
elif protocol == "socks4":
@@ -84,23 +84,27 @@ class Proxy:
proxy_type = ProxyType.HTTP
elif protocol == "https":
proxy_type = ProxyType.HTTPS
line = rest
# Парсим части
# Поддержка формата login:pass@ip:port
login = password = None
if "@" in line:
creds, line = line.rsplit("@", 1)
if ":" in creds:
login, password = creds.split(":", 1)
# Парсим ip:port или ip:port:login:pass
parts = line.split(":")
if len(parts) == 2:
return cls(ip=parts[0], port=parts[1], proxy_type=proxy_type)
return cls(ip=parts[0], port=parts[1], proxy_type=proxy_type,
login=login, password=password)
elif len(parts) == 4:
return cls(
ip=parts[0],
port=parts[1],
login=parts[2],
password=parts[3],
proxy_type=proxy_type
)
return cls(ip=parts[0], port=parts[1],
login=parts[2], password=parts[3],
proxy_type=proxy_type)
return None
@@ -294,9 +298,12 @@ class ProxyManager:
continue
working = self._working_status.get(proxy.id, True)
scheme = proxy.proxy_type.value # socks5, http, etc.
creds = f"{proxy.login}:{proxy.password}@" if proxy.login else ""
new_line = f"{scheme}://{creds}{proxy.ip}:{proxy.port}"
scheme = proxy.proxy_type.value
# Формат совместимый с from_line: scheme://ip:port:login:pass
if proxy.login and proxy.password:
new_line = f"{scheme}://{proxy.ip}:{proxy.port}:{proxy.login}:{proxy.password}"
else:
new_line = f"{scheme}://{proxy.ip}:{proxy.port}"
if not working:
new_line = f"!{new_line}"
@@ -410,6 +417,19 @@ class ProxyManager:
loop = asyncio.get_running_loop()
await loop.run_in_executor(None, self._save_proxies_file)
def reload(self) -> int:
"""Перезагружает прокси из файла. Возвращает количество загруженных."""
self._proxies.clear()
self._working_status.clear()
self._in_use.clear()
self._usage_count.clear()
self._cooldown_until.clear()
self._used_ids.clear()
self._needs_detection.clear()
self._load_proxies()
logger.info(f"Proxies reloaded: {len(self._proxies)}")
return len(self._proxies)
def get_stats(self) -> dict:
"""Статистика прокси."""
loop = asyncio.get_running_loop()
+16 -6
View File
@@ -188,16 +188,26 @@ class BrowserService:
else:
return VisitResult(url=url, success=False, error="No proxy available")
# Определяем тип ошибки: ошибка соединения (прокси сломан) vs ошибка загрузки (прокси ok)
is_proxy_dead = result.error and any(
k in result.error for k in ("502", "Bad Gateway", "SOCKS", "NS_ERROR_PROXY")
)
is_load_error = result.error and not is_proxy_dead and any(
k in result.error for k in ("Timeout", "ERR_", "NS_ERROR_", "Connection")
)
if proxy:
await self.proxy_manager.release_proxy(proxy, result.success)
# Таймаут/ошибка загрузки — прокси не виноват, освобождаем без штрафа
release_success = True if is_load_error else result.success
await self.proxy_manager.release_proxy(proxy, release_success)
if use_socks5:
await self.socks5_pool.release(proxy)
# Если таймаут или соединение не прошло — помечаем прокси как нерабочий и меняем
if not result.success and result.error and any(
k in result.error for k in ("Timeout", "ERR_", "Connection", "SOCKS", "NS_ERROR_", "502", "Bad Gateway")
):
logger.warning(f"Visit attempt {attempt + 1} bad proxy, retrying with new")
if is_proxy_dead:
logger.warning(f"Visit attempt {attempt + 1} proxy connection failed, retrying with new")
continue
elif is_load_error:
logger.warning(f"Visit attempt {attempt + 1} page load error (proxy ok), retrying")
continue
return result