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() 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") @dp.callback_query(F.data == "bot_restart_confirm")
async def cb_restart_confirm(callback: CallbackQuery): async def cb_restart_confirm(callback: CallbackQuery):
if not await require_admin(callback): if not await require_admin(callback):
@@ -1685,6 +1693,7 @@ class BotInterface:
) )
builder = InlineKeyboardBuilder() builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="🔄 Обновить", callback_data="menu_status")) 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="bot_restart_confirm"))
builder.row(InlineKeyboardButton(text="🔙 В меню", callback_data="menu_main")) builder.row(InlineKeyboardButton(text="🔙 В меню", callback_data="menu_main"))
await self._edit_or_send(message, text, builder.as_markup(), edit) await self._edit_or_send(message, text, builder.as_markup(), edit)
@@ -2166,7 +2175,8 @@ class BotInterface:
delay = params.get_delay() delay = params.get_delay()
series_size = params.get_series_size() series_size = params.get_series_size()
logger.info( 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"delay {delay}s ({delay//60}m {delay%60}s), "
f"reading {params.min_reading}-{params.max_reading}s, " f"reading {params.min_reading}-{params.max_reading}s, "
f"done {params.successful_visits}/{max_v}" f"done {params.successful_visits}/{max_v}"
+32 -12
View File
@@ -87,19 +87,23 @@ class Proxy:
line = rest 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(":") parts = line.split(":")
if len(parts) == 2: 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: elif len(parts) == 4:
return cls( return cls(ip=parts[0], port=parts[1],
ip=parts[0], login=parts[2], password=parts[3],
port=parts[1], proxy_type=proxy_type)
login=parts[2],
password=parts[3],
proxy_type=proxy_type
)
return None return None
@@ -294,9 +298,12 @@ class ProxyManager:
continue continue
working = self._working_status.get(proxy.id, True) working = self._working_status.get(proxy.id, True)
scheme = proxy.proxy_type.value # socks5, http, etc. scheme = proxy.proxy_type.value
creds = f"{proxy.login}:{proxy.password}@" if proxy.login else "" # Формат совместимый с from_line: scheme://ip:port:login:pass
new_line = f"{scheme}://{creds}{proxy.ip}:{proxy.port}" 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: if not working:
new_line = f"!{new_line}" new_line = f"!{new_line}"
@@ -410,6 +417,19 @@ class ProxyManager:
loop = asyncio.get_running_loop() loop = asyncio.get_running_loop()
await loop.run_in_executor(None, self._save_proxies_file) 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: def get_stats(self) -> dict:
"""Статистика прокси.""" """Статистика прокси."""
loop = asyncio.get_running_loop() loop = asyncio.get_running_loop()
+16 -6
View File
@@ -188,16 +188,26 @@ class BrowserService:
else: else:
return VisitResult(url=url, success=False, error="No proxy available") 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: 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: if use_socks5:
await self.socks5_pool.release(proxy) await self.socks5_pool.release(proxy)
# Если таймаут или соединение не прошло — помечаем прокси как нерабочий и меняем if is_proxy_dead:
if not result.success and result.error and any( logger.warning(f"Visit attempt {attempt + 1} proxy connection failed, retrying with new")
k in result.error for k in ("Timeout", "ERR_", "Connection", "SOCKS", "NS_ERROR_", "502", "Bad Gateway") continue
): elif is_load_error:
logger.warning(f"Visit attempt {attempt + 1} bad proxy, retrying with new") logger.warning(f"Visit attempt {attempt + 1} page load error (proxy ok), retrying")
continue continue
return result return result