asockslib 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- asockslib-0.1.0/PKG-INFO +228 -0
- asockslib-0.1.0/README.md +199 -0
- asockslib-0.1.0/pyproject.toml +92 -0
- asockslib-0.1.0/src/asockslib/__init__.py +117 -0
- asockslib-0.1.0/src/asockslib/_console.py +18 -0
- asockslib-0.1.0/src/asockslib/_port_utils.py +132 -0
- asockslib-0.1.0/src/asockslib/benchmark.py +365 -0
- asockslib-0.1.0/src/asockslib/cli/__init__.py +72 -0
- asockslib-0.1.0/src/asockslib/cli/_helpers.py +162 -0
- asockslib-0.1.0/src/asockslib/cli/_output.py +52 -0
- asockslib-0.1.0/src/asockslib/cli/api_commands.py +377 -0
- asockslib-0.1.0/src/asockslib/cli/commands.py +485 -0
- asockslib-0.1.0/src/asockslib/client.py +634 -0
- asockslib-0.1.0/src/asockslib/exceptions.py +89 -0
- asockslib-0.1.0/src/asockslib/geo.json +649269 -0
- asockslib-0.1.0/src/asockslib/geo_picker/__init__.py +30 -0
- asockslib-0.1.0/src/asockslib/geo_picker/_completer.py +90 -0
- asockslib-0.1.0/src/asockslib/geo_picker/_messages.py +89 -0
- asockslib-0.1.0/src/asockslib/geo_picker/_types.py +89 -0
- asockslib-0.1.0/src/asockslib/geo_picker/picker.py +667 -0
- asockslib-0.1.0/src/asockslib/models/__init__.py +72 -0
- asockslib-0.1.0/src/asockslib/models/directory.py +65 -0
- asockslib-0.1.0/src/asockslib/models/enums.py +65 -0
- asockslib-0.1.0/src/asockslib/models/port.py +187 -0
- asockslib-0.1.0/src/asockslib/models/requests.py +89 -0
- asockslib-0.1.0/src/asockslib/models/responses.py +20 -0
- asockslib-0.1.0/src/asockslib/proxy_pool.py +659 -0
- asockslib-0.1.0/src/asockslib/quick.py +174 -0
- asockslib-0.1.0/src/asockslib/smart_proxy.py +251 -0
asockslib-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: asockslib
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Premium Python library and CLI for the ASocks Proxy API
|
|
5
|
+
Keywords: proxy,asocks,socks5,http-proxy,rotating-proxy
|
|
6
|
+
Author: bot4ka
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Topic :: Internet :: Proxy Servers
|
|
14
|
+
Classifier: Typing :: Typed
|
|
15
|
+
Requires-Dist: beartype>=0.22.9
|
|
16
|
+
Requires-Dist: httpx>=0.28.1
|
|
17
|
+
Requires-Dist: pydantic>=2.12.5
|
|
18
|
+
Requires-Dist: questionary>=2.1.1
|
|
19
|
+
Requires-Dist: rich>=14.3.3
|
|
20
|
+
Requires-Dist: socksio>=1.0.0
|
|
21
|
+
Requires-Dist: tenacity>=9.1.4
|
|
22
|
+
Requires-Dist: typer>=0.24.1
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Project-URL: Documentation, https://bot4ka.github.io/asockslib
|
|
25
|
+
Project-URL: Homepage, https://github.com/bot4ka/asockslib
|
|
26
|
+
Project-URL: Issues, https://github.com/bot4ka/asockslib/issues
|
|
27
|
+
Project-URL: Repository, https://github.com/bot4ka/asockslib
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# ASocksLib
|
|
31
|
+
|
|
32
|
+
Premium Python library and CLI for the [ASocks Proxy API](https://docs.asocks.com/en/).
|
|
33
|
+
|
|
34
|
+
[](https://github.com/bot4ka/asockslib/actions/workflows/ci.yml)
|
|
35
|
+
[](https://www.python.org/downloads/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
| Feature | Description |
|
|
43
|
+
|---------|-------------|
|
|
44
|
+
| **One-liner API** | Get working proxies in a single function call |
|
|
45
|
+
| **Async Client** | Fully typed `httpx` client, Pydantic models, configurable retry/back-off on 429/5xx/network, typed errors |
|
|
46
|
+
| **Smart Proxy** | Health checking, auto-rotation, and self-healing proxy manager |
|
|
47
|
+
| **Proxy Pool** | Zero-traffic pool for 100,000+ accounts — detects dead proxies via API, sticky per-account mapping, pluggable persistence, optional ping-ranked selection |
|
|
48
|
+
| **CLI** | Interactive wizard, bulk generation, clipboard auto-copy |
|
|
49
|
+
| **18 Templates** | Built-in output formats for AdsPower, Dolphin Anty, GoLogin, etc. |
|
|
50
|
+
| **Export** | `.txt`, `.json`, `.csv` |
|
|
51
|
+
| **Type Safe** | Strict `mypy` + `pyright` + `beartype` runtime checks |
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install asockslib
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or with [uv](https://docs.astral.sh/uv/):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
uv add asockslib
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
Set your API key:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
export ASOCKS_API_KEY="sk-your-api-key"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### One-liner
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
from asockslib import get_proxies
|
|
78
|
+
|
|
79
|
+
urls = asyncio.run(get_proxies("US", count=10))
|
|
80
|
+
# → ["socks5://user:pass@host:port", ...]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Full API Client
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import asyncio
|
|
87
|
+
from asockslib import ASocksClient, CreatePortRequest
|
|
88
|
+
|
|
89
|
+
async def main():
|
|
90
|
+
async with ASocksClient(api_key="sk-...") as client:
|
|
91
|
+
balance = await client.get_balance()
|
|
92
|
+
print(f"Balance: ${balance.balance:.2f}")
|
|
93
|
+
|
|
94
|
+
ports = await client.create_ports(
|
|
95
|
+
CreatePortRequest(country_code="US", count=5)
|
|
96
|
+
)
|
|
97
|
+
for p in ports:
|
|
98
|
+
print(p.proxy_url)
|
|
99
|
+
|
|
100
|
+
asyncio.run(main())
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Smart Proxy (auto-rotation)
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from asockslib import ASocksClient, SmartProxy
|
|
107
|
+
|
|
108
|
+
async with ASocksClient(api_key="sk-...") as client:
|
|
109
|
+
smart = SmartProxy(client, country_code="US")
|
|
110
|
+
await smart.initialize(pool_size=5)
|
|
111
|
+
|
|
112
|
+
proxy = await smart.get_proxy() # auto-heals on failure
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Proxy Pool (100,000+ accounts)
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from asockslib import ASocksClient, ProxyPool, PoolStrategy
|
|
119
|
+
|
|
120
|
+
async with ASocksClient(api_key="sk-...") as client:
|
|
121
|
+
pool = ProxyPool(
|
|
122
|
+
client,
|
|
123
|
+
country_code="US",
|
|
124
|
+
city="New York", # geo-targeting: country + city
|
|
125
|
+
pool_size=100,
|
|
126
|
+
strategy=PoolStrategy.STICKY, # each account pinned to its own proxy
|
|
127
|
+
)
|
|
128
|
+
await pool.initialize()
|
|
129
|
+
|
|
130
|
+
url = await pool.get_proxy("account_42") # sticky assignment
|
|
131
|
+
# On failure — auto-replaces via API (zero traffic waste)
|
|
132
|
+
await pool.report_failure("account_42")
|
|
133
|
+
url = await pool.get_proxy("account_42") # new same-geo proxy!
|
|
134
|
+
|
|
135
|
+
await pool.shutdown()
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Persistence across restarts** — supply a `ProxyStore` so `account_id → port_id`
|
|
139
|
+
bindings survive a process restart (mapping is otherwise in-memory only):
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
class RedisStore: # implement against Redis / SQL / file — your backend
|
|
143
|
+
async def load(self) -> dict[str, int]: ...
|
|
144
|
+
async def save(self, account_id: str, port_id: int) -> None: ...
|
|
145
|
+
async def delete(self, account_id: str) -> None: ...
|
|
146
|
+
|
|
147
|
+
pool = ProxyPool(client, country_code="US", pool_size=100, store=RedisStore())
|
|
148
|
+
await pool.initialize() # restores bindings from the store
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Ping-ranked selection** — over-provision, benchmark, keep the fastest
|
|
152
|
+
(default off = zero-traffic startup):
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
pool = ProxyPool(
|
|
156
|
+
client, country_code="US", pool_size=100,
|
|
157
|
+
benchmark_on_init=True, benchmark_oversample=2.0, # test 200, keep fastest 100
|
|
158
|
+
)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Reliability & errors
|
|
162
|
+
|
|
163
|
+
The client retries **429, 5xx and transient network errors** with configurable
|
|
164
|
+
exponential back-off. Non-idempotent `POST` (create-port) is retried only on 429,
|
|
165
|
+
so a timeout can never silently double-create paid ports.
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from asockslib import ASocksClient, APIConnectionError, RateLimitError, ASocksError
|
|
169
|
+
|
|
170
|
+
client = ASocksClient(
|
|
171
|
+
api_key="sk-...",
|
|
172
|
+
max_retries=5, # attempts per request
|
|
173
|
+
retry_backoff_base=1.0, # attempt n waits base * 2**(n-1), capped at max
|
|
174
|
+
retry_backoff_max=30.0,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
await client.get_balance()
|
|
179
|
+
except APIConnectionError as e: # network unreachable after all retries
|
|
180
|
+
...
|
|
181
|
+
except RateLimitError as e: # 429 after all retries
|
|
182
|
+
...
|
|
183
|
+
except ASocksError as e: # any library error — has .status_code / .message
|
|
184
|
+
...
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## CLI
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Interactive wizard
|
|
191
|
+
asocks wizard
|
|
192
|
+
|
|
193
|
+
# Quick proxy generation
|
|
194
|
+
asocks get US -n 10
|
|
195
|
+
|
|
196
|
+
# Custom template + export
|
|
197
|
+
asocks get US -n 50 -f json -o proxies.json
|
|
198
|
+
|
|
199
|
+
# Account management
|
|
200
|
+
asocks balance
|
|
201
|
+
asocks list
|
|
202
|
+
asocks info 12345
|
|
203
|
+
asocks delete 12345
|
|
204
|
+
|
|
205
|
+
# Raw API
|
|
206
|
+
asocks api countries
|
|
207
|
+
asocks api generate 5 --country DE
|
|
208
|
+
asocks api whitelist-add 203.0.113.42
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Documentation
|
|
212
|
+
|
|
213
|
+
Full docs: **[bot4ka.github.io/asockslib](https://bot4ka.github.io/asockslib)**
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
uv sync # install dependencies
|
|
219
|
+
uv run pytest # run tests
|
|
220
|
+
uv run pyright # type checking
|
|
221
|
+
uv run ruff check . # linting
|
|
222
|
+
uv run python generate_docs.py # generate docs
|
|
223
|
+
cd docs && npm run dev # start docs dev server
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# ASocksLib
|
|
2
|
+
|
|
3
|
+
Premium Python library and CLI for the [ASocks Proxy API](https://docs.asocks.com/en/).
|
|
4
|
+
|
|
5
|
+
[](https://github.com/bot4ka/asockslib/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
| Feature | Description |
|
|
14
|
+
|---------|-------------|
|
|
15
|
+
| **One-liner API** | Get working proxies in a single function call |
|
|
16
|
+
| **Async Client** | Fully typed `httpx` client, Pydantic models, configurable retry/back-off on 429/5xx/network, typed errors |
|
|
17
|
+
| **Smart Proxy** | Health checking, auto-rotation, and self-healing proxy manager |
|
|
18
|
+
| **Proxy Pool** | Zero-traffic pool for 100,000+ accounts — detects dead proxies via API, sticky per-account mapping, pluggable persistence, optional ping-ranked selection |
|
|
19
|
+
| **CLI** | Interactive wizard, bulk generation, clipboard auto-copy |
|
|
20
|
+
| **18 Templates** | Built-in output formats for AdsPower, Dolphin Anty, GoLogin, etc. |
|
|
21
|
+
| **Export** | `.txt`, `.json`, `.csv` |
|
|
22
|
+
| **Type Safe** | Strict `mypy` + `pyright` + `beartype` runtime checks |
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install asockslib
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or with [uv](https://docs.astral.sh/uv/):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv add asockslib
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
Set your API key:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
export ASOCKS_API_KEY="sk-your-api-key"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### One-liner
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import asyncio
|
|
48
|
+
from asockslib import get_proxies
|
|
49
|
+
|
|
50
|
+
urls = asyncio.run(get_proxies("US", count=10))
|
|
51
|
+
# → ["socks5://user:pass@host:port", ...]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Full API Client
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import asyncio
|
|
58
|
+
from asockslib import ASocksClient, CreatePortRequest
|
|
59
|
+
|
|
60
|
+
async def main():
|
|
61
|
+
async with ASocksClient(api_key="sk-...") as client:
|
|
62
|
+
balance = await client.get_balance()
|
|
63
|
+
print(f"Balance: ${balance.balance:.2f}")
|
|
64
|
+
|
|
65
|
+
ports = await client.create_ports(
|
|
66
|
+
CreatePortRequest(country_code="US", count=5)
|
|
67
|
+
)
|
|
68
|
+
for p in ports:
|
|
69
|
+
print(p.proxy_url)
|
|
70
|
+
|
|
71
|
+
asyncio.run(main())
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Smart Proxy (auto-rotation)
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from asockslib import ASocksClient, SmartProxy
|
|
78
|
+
|
|
79
|
+
async with ASocksClient(api_key="sk-...") as client:
|
|
80
|
+
smart = SmartProxy(client, country_code="US")
|
|
81
|
+
await smart.initialize(pool_size=5)
|
|
82
|
+
|
|
83
|
+
proxy = await smart.get_proxy() # auto-heals on failure
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Proxy Pool (100,000+ accounts)
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from asockslib import ASocksClient, ProxyPool, PoolStrategy
|
|
90
|
+
|
|
91
|
+
async with ASocksClient(api_key="sk-...") as client:
|
|
92
|
+
pool = ProxyPool(
|
|
93
|
+
client,
|
|
94
|
+
country_code="US",
|
|
95
|
+
city="New York", # geo-targeting: country + city
|
|
96
|
+
pool_size=100,
|
|
97
|
+
strategy=PoolStrategy.STICKY, # each account pinned to its own proxy
|
|
98
|
+
)
|
|
99
|
+
await pool.initialize()
|
|
100
|
+
|
|
101
|
+
url = await pool.get_proxy("account_42") # sticky assignment
|
|
102
|
+
# On failure — auto-replaces via API (zero traffic waste)
|
|
103
|
+
await pool.report_failure("account_42")
|
|
104
|
+
url = await pool.get_proxy("account_42") # new same-geo proxy!
|
|
105
|
+
|
|
106
|
+
await pool.shutdown()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Persistence across restarts** — supply a `ProxyStore` so `account_id → port_id`
|
|
110
|
+
bindings survive a process restart (mapping is otherwise in-memory only):
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
class RedisStore: # implement against Redis / SQL / file — your backend
|
|
114
|
+
async def load(self) -> dict[str, int]: ...
|
|
115
|
+
async def save(self, account_id: str, port_id: int) -> None: ...
|
|
116
|
+
async def delete(self, account_id: str) -> None: ...
|
|
117
|
+
|
|
118
|
+
pool = ProxyPool(client, country_code="US", pool_size=100, store=RedisStore())
|
|
119
|
+
await pool.initialize() # restores bindings from the store
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Ping-ranked selection** — over-provision, benchmark, keep the fastest
|
|
123
|
+
(default off = zero-traffic startup):
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
pool = ProxyPool(
|
|
127
|
+
client, country_code="US", pool_size=100,
|
|
128
|
+
benchmark_on_init=True, benchmark_oversample=2.0, # test 200, keep fastest 100
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Reliability & errors
|
|
133
|
+
|
|
134
|
+
The client retries **429, 5xx and transient network errors** with configurable
|
|
135
|
+
exponential back-off. Non-idempotent `POST` (create-port) is retried only on 429,
|
|
136
|
+
so a timeout can never silently double-create paid ports.
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from asockslib import ASocksClient, APIConnectionError, RateLimitError, ASocksError
|
|
140
|
+
|
|
141
|
+
client = ASocksClient(
|
|
142
|
+
api_key="sk-...",
|
|
143
|
+
max_retries=5, # attempts per request
|
|
144
|
+
retry_backoff_base=1.0, # attempt n waits base * 2**(n-1), capped at max
|
|
145
|
+
retry_backoff_max=30.0,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
await client.get_balance()
|
|
150
|
+
except APIConnectionError as e: # network unreachable after all retries
|
|
151
|
+
...
|
|
152
|
+
except RateLimitError as e: # 429 after all retries
|
|
153
|
+
...
|
|
154
|
+
except ASocksError as e: # any library error — has .status_code / .message
|
|
155
|
+
...
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## CLI
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Interactive wizard
|
|
162
|
+
asocks wizard
|
|
163
|
+
|
|
164
|
+
# Quick proxy generation
|
|
165
|
+
asocks get US -n 10
|
|
166
|
+
|
|
167
|
+
# Custom template + export
|
|
168
|
+
asocks get US -n 50 -f json -o proxies.json
|
|
169
|
+
|
|
170
|
+
# Account management
|
|
171
|
+
asocks balance
|
|
172
|
+
asocks list
|
|
173
|
+
asocks info 12345
|
|
174
|
+
asocks delete 12345
|
|
175
|
+
|
|
176
|
+
# Raw API
|
|
177
|
+
asocks api countries
|
|
178
|
+
asocks api generate 5 --country DE
|
|
179
|
+
asocks api whitelist-add 203.0.113.42
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Documentation
|
|
183
|
+
|
|
184
|
+
Full docs: **[bot4ka.github.io/asockslib](https://bot4ka.github.io/asockslib)**
|
|
185
|
+
|
|
186
|
+
## Development
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
uv sync # install dependencies
|
|
190
|
+
uv run pytest # run tests
|
|
191
|
+
uv run pyright # type checking
|
|
192
|
+
uv run ruff check . # linting
|
|
193
|
+
uv run python generate_docs.py # generate docs
|
|
194
|
+
cd docs && npm run dev # start docs dev server
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "asockslib"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Premium Python library and CLI for the ASocks Proxy API"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
authors = [{ name = "bot4ka" }]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
keywords = ["proxy", "asocks", "socks5", "http-proxy", "rotating-proxy"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"License :: OSI Approved :: MIT License",
|
|
14
|
+
"Programming Language :: Python :: 3.12",
|
|
15
|
+
"Programming Language :: Python :: 3.13",
|
|
16
|
+
"Topic :: Internet :: Proxy Servers",
|
|
17
|
+
"Typing :: Typed",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"beartype>=0.22.9",
|
|
21
|
+
"httpx>=0.28.1",
|
|
22
|
+
"pydantic>=2.12.5",
|
|
23
|
+
"questionary>=2.1.1",
|
|
24
|
+
"rich>=14.3.3",
|
|
25
|
+
"socksio>=1.0.0",
|
|
26
|
+
"tenacity>=9.1.4",
|
|
27
|
+
"typer>=0.24.1",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/bot4ka/asockslib"
|
|
32
|
+
Documentation = "https://bot4ka.github.io/asockslib"
|
|
33
|
+
Repository = "https://github.com/bot4ka/asockslib"
|
|
34
|
+
Issues = "https://github.com/bot4ka/asockslib/issues"
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
asocks = "asockslib.cli:app"
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
requires = ["uv_build>=0.8.4,<0.9.0"]
|
|
41
|
+
build-backend = "uv_build"
|
|
42
|
+
|
|
43
|
+
[dependency-groups]
|
|
44
|
+
dev = [
|
|
45
|
+
"mypy>=1.19.1",
|
|
46
|
+
"pyright>=1.1.408",
|
|
47
|
+
"pytest>=9.0.2",
|
|
48
|
+
"pytest-asyncio>=1.3.0",
|
|
49
|
+
"pytest-httpx>=0.36.0",
|
|
50
|
+
"ruff>=0.15.4",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[tool.mypy]
|
|
54
|
+
strict = true
|
|
55
|
+
python_version = "3.12"
|
|
56
|
+
|
|
57
|
+
[tool.pyright]
|
|
58
|
+
typeCheckingMode = "strict"
|
|
59
|
+
pythonVersion = "3.12"
|
|
60
|
+
|
|
61
|
+
[[tool.pyright.executionEnvironments]]
|
|
62
|
+
# White-box unit tests deliberately reach into private attributes/methods
|
|
63
|
+
# (_slots, _is_healthy, _fetch_matching_ports, ...) to test internal state
|
|
64
|
+
# directly — that is the intended test design, not a leak of encapsulation.
|
|
65
|
+
root = "tests"
|
|
66
|
+
reportPrivateUsage = false
|
|
67
|
+
|
|
68
|
+
[[tool.pyright.executionEnvironments]]
|
|
69
|
+
# Typer registers these functions as CLI commands via the `@app.command()`
|
|
70
|
+
# decorator at runtime; pyright's static analysis doesn't see that use and
|
|
71
|
+
# flags every command as dead code.
|
|
72
|
+
root = "src/asockslib/cli"
|
|
73
|
+
reportUnusedFunction = false
|
|
74
|
+
|
|
75
|
+
[[tool.pyright.executionEnvironments]]
|
|
76
|
+
root = "."
|
|
77
|
+
|
|
78
|
+
[tool.ruff]
|
|
79
|
+
target-version = "py312"
|
|
80
|
+
line-length = 100
|
|
81
|
+
|
|
82
|
+
[tool.ruff.lint]
|
|
83
|
+
select = ["E", "F", "I", "N", "UP", "ANN", "B", "SIM", "TCH"]
|
|
84
|
+
|
|
85
|
+
[tool.ruff.lint.per-file-ignores]
|
|
86
|
+
# Embedded Markdown/MDX template strings (prose, tables) — wrapping mid-content
|
|
87
|
+
# would corrupt rendered docs; the 100-col limit doesn't apply to prose.
|
|
88
|
+
"generate_docs.py" = ["E501"]
|
|
89
|
+
|
|
90
|
+
[tool.pytest.ini_options]
|
|
91
|
+
asyncio_mode = "auto"
|
|
92
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""ASocksLib — Python library and CLI for the ASocks Proxy API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from asockslib.benchmark import (
|
|
6
|
+
CountryPingResult,
|
|
7
|
+
FindBestResult,
|
|
8
|
+
ProxyBenchmarkResult,
|
|
9
|
+
benchmark_proxies,
|
|
10
|
+
find_best_proxies,
|
|
11
|
+
ping_proxy,
|
|
12
|
+
select_best_proxies,
|
|
13
|
+
)
|
|
14
|
+
from asockslib.client import ASocksClient
|
|
15
|
+
from asockslib.exceptions import (
|
|
16
|
+
APIConnectionError,
|
|
17
|
+
ASocksError,
|
|
18
|
+
AuthenticationError,
|
|
19
|
+
InsufficientBalanceError,
|
|
20
|
+
NoAvailableProxyError,
|
|
21
|
+
PortNotFoundError,
|
|
22
|
+
ProxyHealthError,
|
|
23
|
+
RateLimitError,
|
|
24
|
+
)
|
|
25
|
+
from asockslib.geo_picker import (
|
|
26
|
+
GeoPicker,
|
|
27
|
+
PickedASN,
|
|
28
|
+
PickedCity,
|
|
29
|
+
PickedConnectionType,
|
|
30
|
+
PickedCountry,
|
|
31
|
+
PickedProxyType,
|
|
32
|
+
PickedServerPortType,
|
|
33
|
+
PickedState,
|
|
34
|
+
)
|
|
35
|
+
from asockslib.models import (
|
|
36
|
+
ASNInfo,
|
|
37
|
+
ASNListResponse,
|
|
38
|
+
AuthType,
|
|
39
|
+
BalanceResponse,
|
|
40
|
+
CityInfo,
|
|
41
|
+
ConnectionType,
|
|
42
|
+
ConnectionTypeId,
|
|
43
|
+
CountryInfo,
|
|
44
|
+
CreatePortRequest,
|
|
45
|
+
CreateTemplateRequest,
|
|
46
|
+
PortFilterParams,
|
|
47
|
+
PortInfo,
|
|
48
|
+
PortListResponse,
|
|
49
|
+
PortStatus,
|
|
50
|
+
ProxyType,
|
|
51
|
+
ProxyTypeId,
|
|
52
|
+
ServerPortType,
|
|
53
|
+
StateInfo,
|
|
54
|
+
UpdatePortRequest,
|
|
55
|
+
UpdateTemplateRequest,
|
|
56
|
+
WhitelistAddRequest,
|
|
57
|
+
)
|
|
58
|
+
from asockslib.proxy_pool import PoolStrategy, ProxyPool, ProxyPoolStats, ProxyStore
|
|
59
|
+
from asockslib.quick import get_proxies, get_proxies_sync
|
|
60
|
+
from asockslib.smart_proxy import SmartProxy
|
|
61
|
+
|
|
62
|
+
__all__ = [
|
|
63
|
+
"APIConnectionError",
|
|
64
|
+
"ASNInfo",
|
|
65
|
+
"ASNListResponse",
|
|
66
|
+
"ASocksClient",
|
|
67
|
+
"ASocksError",
|
|
68
|
+
"AuthType",
|
|
69
|
+
"AuthenticationError",
|
|
70
|
+
"BalanceResponse",
|
|
71
|
+
"CityInfo",
|
|
72
|
+
"ConnectionType",
|
|
73
|
+
"ConnectionTypeId",
|
|
74
|
+
"CountryInfo",
|
|
75
|
+
"CountryPingResult",
|
|
76
|
+
"CreatePortRequest",
|
|
77
|
+
"CreateTemplateRequest",
|
|
78
|
+
"FindBestResult",
|
|
79
|
+
"GeoPicker",
|
|
80
|
+
"InsufficientBalanceError",
|
|
81
|
+
"NoAvailableProxyError",
|
|
82
|
+
"PickedASN",
|
|
83
|
+
"PickedCity",
|
|
84
|
+
"PickedConnectionType",
|
|
85
|
+
"PickedCountry",
|
|
86
|
+
"PickedProxyType",
|
|
87
|
+
"PickedServerPortType",
|
|
88
|
+
"PickedState",
|
|
89
|
+
"PoolStrategy",
|
|
90
|
+
"PortFilterParams",
|
|
91
|
+
"PortInfo",
|
|
92
|
+
"PortListResponse",
|
|
93
|
+
"PortNotFoundError",
|
|
94
|
+
"PortStatus",
|
|
95
|
+
"ProxyBenchmarkResult",
|
|
96
|
+
"ProxyHealthError",
|
|
97
|
+
"ProxyPool",
|
|
98
|
+
"ProxyPoolStats",
|
|
99
|
+
"ProxyStore",
|
|
100
|
+
"ProxyType",
|
|
101
|
+
"ProxyTypeId",
|
|
102
|
+
"RateLimitError",
|
|
103
|
+
"ServerPortType",
|
|
104
|
+
"SmartProxy",
|
|
105
|
+
"StateInfo",
|
|
106
|
+
"UpdatePortRequest",
|
|
107
|
+
"UpdateTemplateRequest",
|
|
108
|
+
"WhitelistAddRequest",
|
|
109
|
+
"benchmark_proxies",
|
|
110
|
+
"find_best_proxies",
|
|
111
|
+
"get_proxies",
|
|
112
|
+
"get_proxies_sync",
|
|
113
|
+
"ping_proxy",
|
|
114
|
+
"select_best_proxies",
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Centralized Rich Console singleton.
|
|
2
|
+
|
|
3
|
+
Every module that needs to print to the terminal should import
|
|
4
|
+
``console`` from here instead of creating its own instance.
|
|
5
|
+
|
|
6
|
+
Usage::
|
|
7
|
+
|
|
8
|
+
from asockslib._console import console
|
|
9
|
+
|
|
10
|
+
console.print("[green]OK[/green]")
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from rich.console import Console
|
|
16
|
+
|
|
17
|
+
console: Console = Console()
|
|
18
|
+
"""Module-level singleton :class:`~rich.console.Console` instance."""
|