99 lines
3.0 KiB
Python
99 lines
3.0 KiB
Python
from typing import Callable, Any, Optional
|
|
from yt_dlp import YoutubeDL
|
|
from database import get_latest_proxy, delete_proxy, format_proxy_url, mark_proxy_success
|
|
|
|
class ProxyError(Exception):
|
|
pass
|
|
|
|
def is_proxy_error(error_msg: str) -> bool:
|
|
proxy_error_keywords = [
|
|
'proxy',
|
|
'connection',
|
|
'timeout',
|
|
'timed out',
|
|
'refused',
|
|
'unreachable',
|
|
'unable to connect',
|
|
'network',
|
|
'failed to connect',
|
|
'connection reset',
|
|
'connection aborted',
|
|
'read timed out',
|
|
'http error 407', # Proxy authentication required
|
|
'tunnel connection failed',
|
|
'connect to host',
|
|
]
|
|
|
|
non_proxy_error_keywords = [
|
|
'requested format is not available',
|
|
'format not available',
|
|
'no video formats',
|
|
'video unavailable',
|
|
'private video',
|
|
'age restricted',
|
|
]
|
|
|
|
error_lower = error_msg.lower()
|
|
|
|
if any(keyword in error_lower for keyword in non_proxy_error_keywords):
|
|
return False
|
|
|
|
return any(keyword in error_lower for keyword in proxy_error_keywords)
|
|
|
|
def execute_with_proxy_retry(
|
|
ydl_opts: dict,
|
|
operation: Callable[[YoutubeDL], Any],
|
|
max_retries: int = 10
|
|
) -> Any:
|
|
attempts = 0
|
|
last_error = None
|
|
|
|
while attempts < max_retries:
|
|
attempts += 1
|
|
proxy_data = None
|
|
|
|
try:
|
|
proxy_data = get_latest_proxy()
|
|
|
|
if proxy_data:
|
|
proxy_url = format_proxy_url(proxy_data)
|
|
ydl_opts_with_proxy = {**ydl_opts, 'proxy': proxy_url}
|
|
print(f"Tentativa {attempts}: Usando proxy {proxy_url} (ID: {proxy_data['id']})")
|
|
else:
|
|
if attempts == 1:
|
|
print(f"Tentativa {attempts}: Nenhum proxy disponível, tentando sem proxy")
|
|
ydl_opts_with_proxy = ydl_opts
|
|
else:
|
|
raise ProxyError("Não há mais proxies disponíveis no banco de dados")
|
|
|
|
with YoutubeDL(ydl_opts_with_proxy) as ydl:
|
|
result = operation(ydl)
|
|
print(f"Operação concluída com sucesso na tentativa {attempts}")
|
|
|
|
if proxy_data:
|
|
mark_proxy_success(proxy_data['id'])
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
error_msg = str(e)
|
|
last_error = e
|
|
|
|
print(f"Erro na tentativa {attempts}: {error_msg}")
|
|
|
|
if is_proxy_error(error_msg):
|
|
if proxy_data:
|
|
print(f"Erro identificado como erro de proxy. Removendo proxy ID {proxy_data['id']}")
|
|
delete_proxy(proxy_data['id'])
|
|
else:
|
|
print("Erro de proxy mas nenhum proxy estava sendo usado")
|
|
|
|
continue
|
|
else:
|
|
print(f"Erro não é relacionado a proxy, lançando exceção")
|
|
raise e
|
|
|
|
raise ProxyError(
|
|
f"Falha após {max_retries} tentativas. Último erro: {last_error}"
|
|
)
|