diff --git a/main.py b/main.py index 7ed72b9..ad95026 100644 --- a/main.py +++ b/main.py @@ -79,9 +79,12 @@ class BotApplication: self.interface.register(self.dispatcher) await self._update_bot_commands() + # Определяем типы прокси без явного протокола + await self.proxy_manager.detect_types() + # Восстанавливаем задачи await self._restore_tasks() - + logger.info(f"Proxies: {self.proxy_manager.count}") logger.info("Bot initialized!") diff --git a/managers/proxy_manager.py b/managers/proxy_manager.py index 0382763..d18b02e 100644 --- a/managers/proxy_manager.py +++ b/managers/proxy_manager.py @@ -163,6 +163,7 @@ class ProxyManager: self._cooldown_until: Dict[str, float] = {} self._working_status: Dict[str, bool] = {} self._used_ids: Set[str] = set() + self._needs_detection: Set[str] = set() # прокси без явного типа self._load_proxies() @@ -181,12 +182,16 @@ class ProxyManager: ] loaded = [] + _has_scheme = {"socks5://", "socks4://", "http://", "https://"} for line in lines: + explicit_type = any(line.lower().startswith(s) for s in _has_scheme) proxy = Proxy.from_line(line, default_type=ProxyType.SOCKS5) if proxy: self._proxies.append(proxy) self._working_status[proxy.id] = True loaded.append(proxy) + if not explicit_type: + self._needs_detection.add(proxy.id) logger.info(f"Loaded {len(loaded)} proxies from {self.proxy_file}") @@ -199,7 +204,42 @@ class ProxyManager: except Exception as e: logger.error(f"Failed to load proxies: {e}", exc_info=True) - + + async def detect_types(self, concurrency: int = 10) -> None: + """Определяет типы прокси у которых тип не задан явно.""" + targets = [p for p in self._proxies if p.id in self._needs_detection] + if not targets: + return + + logger.info(f"Detecting proxy types for {len(targets)} proxies...") + sem = asyncio.Semaphore(concurrency) + detected = {"socks5": 0, "socks4": 0, "http": 0, "failed": 0} + + async def _detect_one(proxy: Proxy): + async with sem: + old_id = proxy.id + ptype = await detect_proxy_type(proxy.ip, proxy.port, proxy.login, proxy.password) + if ptype and ptype != proxy.proxy_type: + self._working_status.pop(old_id, None) + self._needs_detection.discard(old_id) + proxy.proxy_type = ptype + self._working_status[proxy.id] = True + detected[ptype.value] += 1 + elif ptype is None: + self._working_status[proxy.id] = False + detected["failed"] += 1 + else: + detected[ptype.value] += 1 + + await asyncio.gather(*[_detect_one(p) for p in targets]) + + self._needs_detection.clear() + logger.info( + f"Proxy detection done — " + f"socks5:{detected['socks5']} socks4:{detected['socks4']} " + f"http:{detected['http']} failed:{detected['failed']}" + ) + def _is_available(self, proxy: Proxy) -> bool: """Проверка доступности прокси.""" proxy_id = proxy.id