Claude commited on
Commit
9a3fa5e
·
unverified ·
1 Parent(s): 091d83c

revert: Remove Hola proxy (blocked by Hola from cloud IPs)

Browse files

Hola permanently blocks requests from cloud/datacenter IPs.
Keep simple PROXY_URL env var support for manual proxy configuration.

Files changed (2) hide show
  1. app.py +2 -15
  2. hola_proxy.py +0 -226
app.py CHANGED
@@ -115,21 +115,8 @@ CHAT_MODELS = [
115
 
116
 
117
  def get_proxy_url() -> str | None:
118
- """Get proxy URL from Hola for YouTube downloads."""
119
- # Check for manual override first
120
- env_proxy = os.environ.get("PROXY_URL")
121
- if env_proxy:
122
- return env_proxy
123
-
124
- # Use Hola proxy for YouTube downloads
125
- try:
126
- from hola_proxy import get_hola_proxy
127
- country = os.environ.get("HOLA_COUNTRY", "us")
128
- proxy_type = os.environ.get("HOLA_PROXY_TYPE", "direct")
129
- return get_hola_proxy(country=country, proxy_type=proxy_type)
130
- except Exception as e:
131
- print(f"Failed to get Hola proxy: {e}")
132
- return None
133
 
134
 
135
  def download_video(url: str, output_dir: str) -> list[dict]:
 
115
 
116
 
117
  def get_proxy_url() -> str | None:
118
+ """Get proxy URL from environment for YouTube downloads."""
119
+ return os.environ.get("PROXY_URL")
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
 
122
  def download_video(url: str, output_dir: str) -> list[dict]:
hola_proxy.py DELETED
@@ -1,226 +0,0 @@
1
- """
2
- Hola Proxy Client - Python implementation based on Snawoot/hola-proxy
3
-
4
- This module provides access to Hola's proxy network for routing traffic
5
- through residential IPs. Unlike the official Hola client, this implementation
6
- does NOT make your connection an exit node for others.
7
-
8
- API flow:
9
- 1. Generate UUID for session
10
- 2. Call background_init to authenticate and get session key
11
- 3. Call zgettunnels to get proxy server addresses
12
- 4. Use returned proxy with authentication
13
- """
14
-
15
- import random
16
- import time
17
- import uuid
18
- from typing import Any
19
-
20
- import requests
21
-
22
- # Hola API endpoints
23
- CCGI_URL = "https://client.hola.org/client_cgi/"
24
- BG_INIT_URL = CCGI_URL + "background_init"
25
- ZGETTUNNELS_URL = CCGI_URL + "zgettunnels"
26
-
27
- # Mimic Chrome extension
28
- EXT_VER = "1.220.419"
29
- EXT_BROWSER = "chrome"
30
- PRODUCT = "cws"
31
-
32
-
33
- def generate_user_uuid() -> str:
34
- """Generate a random UUID for Hola session."""
35
- return uuid.uuid4().hex
36
-
37
-
38
- def get_chrome_version() -> str:
39
- """Return a plausible Chrome version string."""
40
- return "120.0.0.0"
41
-
42
-
43
- class HolaProxyClient:
44
- """Client for Hola's proxy network."""
45
-
46
- def __init__(self, country: str = "us", proxy_type: str = "lum"):
47
- """
48
- Initialize Hola proxy client.
49
-
50
- Args:
51
- country: Two-letter country code (us, uk, de, etc.)
52
- proxy_type: Type of proxy:
53
- - "direct": Datacenter proxies (faster, but may be blocked)
54
- - "lum": Residential IPs via Luminati/Bright Data (slower, less blocked)
55
- """
56
- self.country = country.lower()
57
- self.proxy_type = proxy_type
58
- self.user_uuid = generate_user_uuid()
59
- self.session_key: int | None = None
60
- self.proxy_host: str | None = None
61
- self.proxy_port: int | None = None
62
- self.agent_key: str | None = None
63
- self._session = requests.Session()
64
- self._session.headers.update({
65
- "User-Agent": f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{get_chrome_version()} Safari/537.36",
66
- })
67
-
68
- def _background_init(self) -> dict[str, Any]:
69
- """
70
- Initialize session with Hola API.
71
-
72
- Returns authentication data including session key.
73
- """
74
- params = {
75
- "login": "1",
76
- "ver": EXT_VER,
77
- "browser": EXT_BROWSER,
78
- "uuid": self.user_uuid,
79
- }
80
-
81
- response = self._session.post(BG_INIT_URL, data=params, timeout=30)
82
- response.raise_for_status()
83
- data = response.json()
84
-
85
- if "blocked" in data:
86
- raise RuntimeError(f"Hola account blocked: {data.get('blocked_msg', 'Unknown reason')}")
87
-
88
- self.session_key = data.get("key")
89
- return data
90
-
91
- def _zgettunnels(self) -> dict[str, Any]:
92
- """
93
- Get tunnel/proxy information from Hola.
94
-
95
- Returns proxy server addresses and authentication.
96
- """
97
- if self.session_key is None:
98
- raise RuntimeError("Must call background_init first")
99
-
100
- params = {
101
- "country": self.country,
102
- "limit": 3,
103
- "ping_id": random.random(),
104
- "ext_ver": EXT_VER,
105
- "browser": EXT_BROWSER,
106
- "product": PRODUCT,
107
- "uuid": self.user_uuid,
108
- "session_key": self.session_key,
109
- "is_premium": 0,
110
- }
111
-
112
- # Add proxy type
113
- if self.proxy_type == "lum":
114
- params["type"] = "lum"
115
- elif self.proxy_type == "direct":
116
- params["type"] = "direct"
117
-
118
- response = self._session.post(ZGETTUNNELS_URL, data=params, timeout=30)
119
- response.raise_for_status()
120
- data = response.json()
121
-
122
- if "agent_key" not in data:
123
- raise RuntimeError(f"Failed to get tunnels: {data}")
124
-
125
- self.agent_key = data["agent_key"]
126
-
127
- # Extract first available proxy
128
- if "ip_list" in data and data["ip_list"]:
129
- ip_info = list(data["ip_list"].values())[0]
130
- self.proxy_host = ip_info.get("ip")
131
- self.proxy_port = int(data.get("port", {}).get("direct", 22222))
132
- elif "agent_types" in data:
133
- # Alternative format
134
- agents = data.get("agent_types", {})
135
- if agents:
136
- agent_type = list(agents.keys())[0]
137
- agent_list = agents[agent_type]
138
- if agent_list:
139
- self.proxy_host = agent_list[0]
140
- self.proxy_port = int(data.get("port", {}).get("direct", 22222))
141
-
142
- return data
143
-
144
- def connect(self) -> str:
145
- """
146
- Connect to Hola and get proxy URL.
147
-
148
- Returns:
149
- Proxy URL in format http://user:pass@host:port
150
- """
151
- # Initialize session
152
- self._background_init()
153
-
154
- # Get tunnels with retry
155
- max_retries = 3
156
- for attempt in range(max_retries):
157
- try:
158
- self._zgettunnels()
159
- break
160
- except Exception as e:
161
- if attempt == max_retries - 1:
162
- raise
163
- time.sleep(2 ** attempt) # Exponential backoff
164
-
165
- if not self.proxy_host or not self.proxy_port:
166
- raise RuntimeError("Failed to obtain proxy server")
167
-
168
- # Build authenticated proxy URL
169
- # Format: user-uuid-country-session:agent_key@host:port
170
- username = f"user-uuid-{self.user_uuid}"
171
- password = self.agent_key
172
-
173
- return f"http://{username}:{password}@{self.proxy_host}:{self.proxy_port}"
174
-
175
- def get_proxy_dict(self) -> dict[str, str]:
176
- """
177
- Get proxy configuration as dict for requests library.
178
-
179
- Returns:
180
- Dict with http and https proxy URLs
181
- """
182
- proxy_url = self.connect()
183
- return {
184
- "http": proxy_url,
185
- "https": proxy_url,
186
- }
187
-
188
-
189
- def get_hola_proxy(country: str = "us", proxy_type: str = "lum") -> str | None:
190
- """
191
- Convenience function to get a Hola proxy URL.
192
-
193
- Args:
194
- country: Two-letter country code
195
- proxy_type: "direct" or "lum" (residential)
196
-
197
- Returns:
198
- Proxy URL or None on failure
199
- """
200
- try:
201
- client = HolaProxyClient(country=country, proxy_type=proxy_type)
202
- return client.connect()
203
- except Exception as e:
204
- print(f"Failed to get Hola proxy: {e}")
205
- return None
206
-
207
-
208
- if __name__ == "__main__":
209
- # Test the client
210
- print("Testing Hola proxy client...")
211
- proxy_url = get_hola_proxy(country="us", proxy_type="direct")
212
- if proxy_url:
213
- print(f"Got proxy: {proxy_url[:50]}...")
214
-
215
- # Test the proxy
216
- try:
217
- response = requests.get(
218
- "https://httpbin.org/ip",
219
- proxies={"http": proxy_url, "https": proxy_url},
220
- timeout=30,
221
- )
222
- print(f"Your IP via proxy: {response.json()}")
223
- except Exception as e:
224
- print(f"Proxy test failed: {e}")
225
- else:
226
- print("Failed to get proxy")