ip2vn 1.0.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.
- ip2vn-1.0.0/LICENSE +21 -0
- ip2vn-1.0.0/PKG-INFO +83 -0
- ip2vn-1.0.0/README.md +67 -0
- ip2vn-1.0.0/ip2vn.egg-info/PKG-INFO +83 -0
- ip2vn-1.0.0/ip2vn.egg-info/SOURCES.txt +8 -0
- ip2vn-1.0.0/ip2vn.egg-info/dependency_links.txt +1 -0
- ip2vn-1.0.0/ip2vn.egg-info/top_level.txt +1 -0
- ip2vn-1.0.0/ip2vn.py +151 -0
- ip2vn-1.0.0/pyproject.toml +24 -0
- ip2vn-1.0.0/setup.cfg +4 -0
ip2vn-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 IP2.VN
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ip2vn-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ip2vn
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: SDK chính thức của IP2.VN — điều khiển proxy xoay IP dân cư Viettel cho bên làm tool tích hợp.
|
|
5
|
+
Author: IP2.VN
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://ip2.vn
|
|
8
|
+
Keywords: ip2,ip2vn,proxy,rotating-proxy,residential-proxy,viettel,sdk
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Topic :: Internet :: Proxy Servers
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# ip2vn
|
|
18
|
+
|
|
19
|
+
SDK Python chính thức của [IP2.VN](https://ip2.vn) — điều khiển proxy xoay IP dân
|
|
20
|
+
cư Viettel cho bên làm tool tích hợp. Không phụ thuộc thư viện ngoài (chỉ dùng
|
|
21
|
+
`urllib` chuẩn), cần Python 3.8+.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install ip2vn
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Mô hình giới thiệu (hoa hồng 10%)
|
|
28
|
+
|
|
29
|
+
Tool của bạn nhúng **mã giới thiệu công khai** của bạn và đưa người dùng đăng ký
|
|
30
|
+
qua `IP2.ref_link('MÃ')`. Người dùng tự mua proxy, tự tạo **key theo từng cổng**
|
|
31
|
+
rồi dán vào tool; bạn ăn 10% chi tiêu của họ.
|
|
32
|
+
|
|
33
|
+
> **An toàn:** chỉ nhúng mã giới thiệu (công khai). TUYỆT ĐỐI không nhúng key,
|
|
34
|
+
> mật khẩu hay token vào tool phát đi — tool nào cũng bung xem được. Key là của
|
|
35
|
+
> chính người dùng cuối, không phải của bạn.
|
|
36
|
+
|
|
37
|
+
## Dùng
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from ip2vn import IP2, IP2Error
|
|
41
|
+
|
|
42
|
+
# Link đưa cho người dùng để họ gắn với bạn:
|
|
43
|
+
print(IP2.ref_link("MÃ_GIỚI_THIỆU_CỦA_BẠN")) # https://ip2.vn/?ref=...
|
|
44
|
+
|
|
45
|
+
# Người dùng dán key cổng của họ vào tool của bạn:
|
|
46
|
+
cong = IP2("ip2_xxxxxxxxxxxx")
|
|
47
|
+
|
|
48
|
+
tin = cong.info() # host, port, ip, cooldown, expire_at, ...
|
|
49
|
+
kq = cong.rotate() # { ip, previous_ip, took, next_allowed_in }
|
|
50
|
+
cong.auto(300) # hẹn tự xoay mỗi 300s (0 để tắt, thấp nhất 180)
|
|
51
|
+
ls = cong.history(limit=20)
|
|
52
|
+
cong.renew(30) # gia hạn 1/7/30 ngày, trừ ví người dùng
|
|
53
|
+
|
|
54
|
+
# Chuỗi proxy sẵn dùng (user/pass proxy do người dùng nhập):
|
|
55
|
+
px = cong.proxy("u", "p")
|
|
56
|
+
print(px["url"]) # http://u:p@host:port
|
|
57
|
+
print(px["tho"]) # host:port:u:p
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
cong.rotate()
|
|
61
|
+
except IP2Error as e:
|
|
62
|
+
print(e.code, e.message, e.retry_after)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Phương thức
|
|
66
|
+
|
|
67
|
+
| Gọi | Trả về |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `info()` | host, port, line, ip, protocol, auto, cooldown, expire_at, rotations |
|
|
70
|
+
| `rotate(wait=True)` | ip, previous_ip, took, next_allowed_in |
|
|
71
|
+
| `auto(giây)` | auto, every, next_at |
|
|
72
|
+
| `history(limit, since)` | total, items[{ip, at}] |
|
|
73
|
+
| `renew(1\|7\|30)` | days_added, charged, wallet_balance, expire_at |
|
|
74
|
+
| `proxy(username, password, protocol)` | host, port, url, tho |
|
|
75
|
+
| `IP2.ref_link(mã)` | `https://ip2.vn/?ref=mã` |
|
|
76
|
+
|
|
77
|
+
Lỗi ném ra `IP2Error` với `.code` (máy đọc), `.message` (tiếng Việt), `.status`
|
|
78
|
+
(HTTP), `.retry_after` (giây, khi dính `cooldown`).
|
|
79
|
+
|
|
80
|
+
Cổng nghe cả HTTP lẫn SOCKS5 trên cùng một port — chọn giao thức chỉ đổi cách
|
|
81
|
+
viết chuỗi, không đổi port.
|
|
82
|
+
|
|
83
|
+
MIT © IP2.VN
|
ip2vn-1.0.0/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# ip2vn
|
|
2
|
+
|
|
3
|
+
SDK Python chính thức của [IP2.VN](https://ip2.vn) — điều khiển proxy xoay IP dân
|
|
4
|
+
cư Viettel cho bên làm tool tích hợp. Không phụ thuộc thư viện ngoài (chỉ dùng
|
|
5
|
+
`urllib` chuẩn), cần Python 3.8+.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install ip2vn
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Mô hình giới thiệu (hoa hồng 10%)
|
|
12
|
+
|
|
13
|
+
Tool của bạn nhúng **mã giới thiệu công khai** của bạn và đưa người dùng đăng ký
|
|
14
|
+
qua `IP2.ref_link('MÃ')`. Người dùng tự mua proxy, tự tạo **key theo từng cổng**
|
|
15
|
+
rồi dán vào tool; bạn ăn 10% chi tiêu của họ.
|
|
16
|
+
|
|
17
|
+
> **An toàn:** chỉ nhúng mã giới thiệu (công khai). TUYỆT ĐỐI không nhúng key,
|
|
18
|
+
> mật khẩu hay token vào tool phát đi — tool nào cũng bung xem được. Key là của
|
|
19
|
+
> chính người dùng cuối, không phải của bạn.
|
|
20
|
+
|
|
21
|
+
## Dùng
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from ip2vn import IP2, IP2Error
|
|
25
|
+
|
|
26
|
+
# Link đưa cho người dùng để họ gắn với bạn:
|
|
27
|
+
print(IP2.ref_link("MÃ_GIỚI_THIỆU_CỦA_BẠN")) # https://ip2.vn/?ref=...
|
|
28
|
+
|
|
29
|
+
# Người dùng dán key cổng của họ vào tool của bạn:
|
|
30
|
+
cong = IP2("ip2_xxxxxxxxxxxx")
|
|
31
|
+
|
|
32
|
+
tin = cong.info() # host, port, ip, cooldown, expire_at, ...
|
|
33
|
+
kq = cong.rotate() # { ip, previous_ip, took, next_allowed_in }
|
|
34
|
+
cong.auto(300) # hẹn tự xoay mỗi 300s (0 để tắt, thấp nhất 180)
|
|
35
|
+
ls = cong.history(limit=20)
|
|
36
|
+
cong.renew(30) # gia hạn 1/7/30 ngày, trừ ví người dùng
|
|
37
|
+
|
|
38
|
+
# Chuỗi proxy sẵn dùng (user/pass proxy do người dùng nhập):
|
|
39
|
+
px = cong.proxy("u", "p")
|
|
40
|
+
print(px["url"]) # http://u:p@host:port
|
|
41
|
+
print(px["tho"]) # host:port:u:p
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
cong.rotate()
|
|
45
|
+
except IP2Error as e:
|
|
46
|
+
print(e.code, e.message, e.retry_after)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Phương thức
|
|
50
|
+
|
|
51
|
+
| Gọi | Trả về |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `info()` | host, port, line, ip, protocol, auto, cooldown, expire_at, rotations |
|
|
54
|
+
| `rotate(wait=True)` | ip, previous_ip, took, next_allowed_in |
|
|
55
|
+
| `auto(giây)` | auto, every, next_at |
|
|
56
|
+
| `history(limit, since)` | total, items[{ip, at}] |
|
|
57
|
+
| `renew(1\|7\|30)` | days_added, charged, wallet_balance, expire_at |
|
|
58
|
+
| `proxy(username, password, protocol)` | host, port, url, tho |
|
|
59
|
+
| `IP2.ref_link(mã)` | `https://ip2.vn/?ref=mã` |
|
|
60
|
+
|
|
61
|
+
Lỗi ném ra `IP2Error` với `.code` (máy đọc), `.message` (tiếng Việt), `.status`
|
|
62
|
+
(HTTP), `.retry_after` (giây, khi dính `cooldown`).
|
|
63
|
+
|
|
64
|
+
Cổng nghe cả HTTP lẫn SOCKS5 trên cùng một port — chọn giao thức chỉ đổi cách
|
|
65
|
+
viết chuỗi, không đổi port.
|
|
66
|
+
|
|
67
|
+
MIT © IP2.VN
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ip2vn
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: SDK chính thức của IP2.VN — điều khiển proxy xoay IP dân cư Viettel cho bên làm tool tích hợp.
|
|
5
|
+
Author: IP2.VN
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://ip2.vn
|
|
8
|
+
Keywords: ip2,ip2vn,proxy,rotating-proxy,residential-proxy,viettel,sdk
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Topic :: Internet :: Proxy Servers
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# ip2vn
|
|
18
|
+
|
|
19
|
+
SDK Python chính thức của [IP2.VN](https://ip2.vn) — điều khiển proxy xoay IP dân
|
|
20
|
+
cư Viettel cho bên làm tool tích hợp. Không phụ thuộc thư viện ngoài (chỉ dùng
|
|
21
|
+
`urllib` chuẩn), cần Python 3.8+.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install ip2vn
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Mô hình giới thiệu (hoa hồng 10%)
|
|
28
|
+
|
|
29
|
+
Tool của bạn nhúng **mã giới thiệu công khai** của bạn và đưa người dùng đăng ký
|
|
30
|
+
qua `IP2.ref_link('MÃ')`. Người dùng tự mua proxy, tự tạo **key theo từng cổng**
|
|
31
|
+
rồi dán vào tool; bạn ăn 10% chi tiêu của họ.
|
|
32
|
+
|
|
33
|
+
> **An toàn:** chỉ nhúng mã giới thiệu (công khai). TUYỆT ĐỐI không nhúng key,
|
|
34
|
+
> mật khẩu hay token vào tool phát đi — tool nào cũng bung xem được. Key là của
|
|
35
|
+
> chính người dùng cuối, không phải của bạn.
|
|
36
|
+
|
|
37
|
+
## Dùng
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from ip2vn import IP2, IP2Error
|
|
41
|
+
|
|
42
|
+
# Link đưa cho người dùng để họ gắn với bạn:
|
|
43
|
+
print(IP2.ref_link("MÃ_GIỚI_THIỆU_CỦA_BẠN")) # https://ip2.vn/?ref=...
|
|
44
|
+
|
|
45
|
+
# Người dùng dán key cổng của họ vào tool của bạn:
|
|
46
|
+
cong = IP2("ip2_xxxxxxxxxxxx")
|
|
47
|
+
|
|
48
|
+
tin = cong.info() # host, port, ip, cooldown, expire_at, ...
|
|
49
|
+
kq = cong.rotate() # { ip, previous_ip, took, next_allowed_in }
|
|
50
|
+
cong.auto(300) # hẹn tự xoay mỗi 300s (0 để tắt, thấp nhất 180)
|
|
51
|
+
ls = cong.history(limit=20)
|
|
52
|
+
cong.renew(30) # gia hạn 1/7/30 ngày, trừ ví người dùng
|
|
53
|
+
|
|
54
|
+
# Chuỗi proxy sẵn dùng (user/pass proxy do người dùng nhập):
|
|
55
|
+
px = cong.proxy("u", "p")
|
|
56
|
+
print(px["url"]) # http://u:p@host:port
|
|
57
|
+
print(px["tho"]) # host:port:u:p
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
cong.rotate()
|
|
61
|
+
except IP2Error as e:
|
|
62
|
+
print(e.code, e.message, e.retry_after)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Phương thức
|
|
66
|
+
|
|
67
|
+
| Gọi | Trả về |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `info()` | host, port, line, ip, protocol, auto, cooldown, expire_at, rotations |
|
|
70
|
+
| `rotate(wait=True)` | ip, previous_ip, took, next_allowed_in |
|
|
71
|
+
| `auto(giây)` | auto, every, next_at |
|
|
72
|
+
| `history(limit, since)` | total, items[{ip, at}] |
|
|
73
|
+
| `renew(1\|7\|30)` | days_added, charged, wallet_balance, expire_at |
|
|
74
|
+
| `proxy(username, password, protocol)` | host, port, url, tho |
|
|
75
|
+
| `IP2.ref_link(mã)` | `https://ip2.vn/?ref=mã` |
|
|
76
|
+
|
|
77
|
+
Lỗi ném ra `IP2Error` với `.code` (máy đọc), `.message` (tiếng Việt), `.status`
|
|
78
|
+
(HTTP), `.retry_after` (giây, khi dính `cooldown`).
|
|
79
|
+
|
|
80
|
+
Cổng nghe cả HTTP lẫn SOCKS5 trên cùng một port — chọn giao thức chỉ đổi cách
|
|
81
|
+
viết chuỗi, không đổi port.
|
|
82
|
+
|
|
83
|
+
MIT © IP2.VN
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ip2vn
|
ip2vn-1.0.0/ip2vn.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""SDK Python chính thức cho IP2.VN — dành cho bên làm tool tích hợp proxy.
|
|
2
|
+
|
|
3
|
+
Mô hình GIỚI THIỆU: tool của bạn nhúng MÃ GIỚI THIỆU CÔNG KHAI của bạn và đẩy
|
|
4
|
+
người dùng đăng ký qua ``IP2.ref_link(ma)``. Người dùng tự mua proxy của IP2.VN,
|
|
5
|
+
bạn ăn hoa hồng giới thiệu trên chi tiêu của họ. Tool điều khiển cổng bằng KEY
|
|
6
|
+
CỦA CHÍNH NGƯỜI DÙNG (họ tự tạo trong bảng điều khiển rồi dán vào tool).
|
|
7
|
+
|
|
8
|
+
── AN TOÀN, đọc kỹ ──
|
|
9
|
+
* Chỉ nhúng MÃ GIỚI THIỆU (công khai) vào tool phát đi. TUYỆT ĐỐI không nhúng
|
|
10
|
+
key, mật khẩu, hay token tài khoản — tool phát ra ngoài là ai cũng bung xem
|
|
11
|
+
được, nhúng bí mật vào là lộ.
|
|
12
|
+
* Key ở đây là key THEO TỪNG CỔNG của người dùng cuối, không phải của bạn.
|
|
13
|
+
* "Tool chỉ chạy khi có key hợp lệ" là chuyện proxy tự lo ở máy chủ: không có
|
|
14
|
+
cổng đã trả tiền thì proxy trả 407.
|
|
15
|
+
|
|
16
|
+
Không phụ thuộc thư viện ngoài (chỉ dùng thư viện chuẩn urllib). Cần Python 3.8+.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import urllib.request
|
|
21
|
+
import urllib.parse
|
|
22
|
+
import urllib.error
|
|
23
|
+
|
|
24
|
+
GOC_API = "https://api.ip2.vn"
|
|
25
|
+
GOC_WEB = "https://ip2.vn"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class IP2Error(Exception):
|
|
29
|
+
"""Lỗi từ API IP2.VN.
|
|
30
|
+
|
|
31
|
+
code: mã máy đọc ('cooldown', 'expired', 'invalid_key'...).
|
|
32
|
+
message: câu tiếng Việt cho người. status: mã HTTP. retry_after: giây chờ.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, code, message=None, status=0, retry_after=None):
|
|
36
|
+
super().__init__(message or code)
|
|
37
|
+
self.code = code
|
|
38
|
+
self.message = message or code
|
|
39
|
+
self.status = status
|
|
40
|
+
self.retry_after = retry_after
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class IP2:
|
|
44
|
+
"""Điều khiển MỘT cổng proxy bằng key của cổng đó.
|
|
45
|
+
|
|
46
|
+
cong = IP2("ip2_xxxxxxxxxxxx")
|
|
47
|
+
tin = cong.info()
|
|
48
|
+
cong.rotate()
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, key, base=GOC_API, timeout=35):
|
|
52
|
+
if not key or not isinstance(key, str):
|
|
53
|
+
raise IP2Error("missing_key", "Thiếu key của cổng.", 0)
|
|
54
|
+
self.key = key
|
|
55
|
+
self.base = base.rstrip("/")
|
|
56
|
+
self.timeout = timeout # rotate chờ IP mới có thể tới ~30s
|
|
57
|
+
|
|
58
|
+
def _goi(self, duong, method="GET", query=None, body=None):
|
|
59
|
+
url = self.base + duong
|
|
60
|
+
if query:
|
|
61
|
+
q = {k: v for k, v in query.items() if v is not None}
|
|
62
|
+
if q:
|
|
63
|
+
url += "?" + urllib.parse.urlencode(q)
|
|
64
|
+
data = json.dumps(body).encode("utf-8") if body is not None else None
|
|
65
|
+
# User-Agent thật: mặc định của urllib giống bot, Cloudflare chặn 403.
|
|
66
|
+
headers = {"X-IP2-Key": self.key,
|
|
67
|
+
"User-Agent": "ip2-sdk-python/1.0 (+https://ip2.vn)"}
|
|
68
|
+
if data is not None:
|
|
69
|
+
headers["content-type"] = "application/json"
|
|
70
|
+
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
|
71
|
+
try:
|
|
72
|
+
with urllib.request.urlopen(req, timeout=self.timeout) as r:
|
|
73
|
+
return json.loads(r.read().decode("utf-8") or "{}")
|
|
74
|
+
except urllib.error.HTTPError as e:
|
|
75
|
+
try:
|
|
76
|
+
j = json.loads(e.read().decode("utf-8") or "{}")
|
|
77
|
+
except Exception:
|
|
78
|
+
j = {}
|
|
79
|
+
ra = j.get("retry_after")
|
|
80
|
+
raise IP2Error(j.get("error", "http_%d" % e.code),
|
|
81
|
+
j.get("message", "Lỗi không rõ."), e.code,
|
|
82
|
+
ra if isinstance(ra, (int, float)) else None)
|
|
83
|
+
except urllib.error.URLError as e:
|
|
84
|
+
reason = getattr(e, "reason", "")
|
|
85
|
+
aborted = isinstance(reason, TimeoutError) or "timed out" in str(reason)
|
|
86
|
+
raise IP2Error("timeout" if aborted else "network_error",
|
|
87
|
+
"Quá hạn chờ máy chủ." if aborted
|
|
88
|
+
else "Không gọi được máy chủ IP2.VN.", 0)
|
|
89
|
+
|
|
90
|
+
def info(self):
|
|
91
|
+
"""Thông tin cổng: host, port, ip hiện tại, hẹn xoay, cooldown, hạn dùng."""
|
|
92
|
+
return self._goi("/v1/info")
|
|
93
|
+
|
|
94
|
+
def rotate(self, wait=True):
|
|
95
|
+
"""Xin IP mới. wait=True (mặc định) chờ tới khi có IP mới.
|
|
96
|
+
|
|
97
|
+
Trả về dict { ip, previous_ip, port, took, next_allowed_in }.
|
|
98
|
+
"""
|
|
99
|
+
return self._goi("/v1/rotate", query={"wait": "true" if wait else "false"})
|
|
100
|
+
|
|
101
|
+
def auto(self, every):
|
|
102
|
+
"""Hẹn giờ tự xoay. every = số giây (thấp nhất 180), 0 để tắt.
|
|
103
|
+
|
|
104
|
+
Trả về { auto, every, next_at }.
|
|
105
|
+
"""
|
|
106
|
+
return self._goi("/v1/auto", method="POST", body={"every": every})
|
|
107
|
+
|
|
108
|
+
def history(self, limit=None, since=None):
|
|
109
|
+
"""Lịch sử IP của cổng, mới nhất trước. since theo ISO 8601.
|
|
110
|
+
|
|
111
|
+
Trả về { total, items: [{ ip, at }] }.
|
|
112
|
+
"""
|
|
113
|
+
return self._goi("/v1/history", query={"limit": limit, "since": since})
|
|
114
|
+
|
|
115
|
+
def renew(self, days):
|
|
116
|
+
"""Gia hạn cổng, trừ ví chính của người dùng. days chỉ nhận 1, 7 hoặc 30.
|
|
117
|
+
|
|
118
|
+
Ví không đủ thì ném IP2Error code 'insufficient_funds' (HTTP 402), không
|
|
119
|
+
trừ gì. Trả về { days_added, charged, wallet_balance, expire_at }.
|
|
120
|
+
"""
|
|
121
|
+
return self._goi("/v1/renew", method="POST", body={"days": days})
|
|
122
|
+
|
|
123
|
+
def proxy(self, username, password, protocol="http"):
|
|
124
|
+
"""Dựng chuỗi proxy sẵn dùng từ host/port của cổng cộng tài khoản proxy.
|
|
125
|
+
|
|
126
|
+
LƯU Ý: user/pass proxy KHÔNG lấy từ API (bí mật của người dùng, máy chủ
|
|
127
|
+
không trả ra) — người dùng tự nhập. Host và port thì SDK đọc từ info().
|
|
128
|
+
|
|
129
|
+
Trả về dict { host, port, url, tho } — url dạng đầy đủ, tho dạng
|
|
130
|
+
host:port:user:pass.
|
|
131
|
+
"""
|
|
132
|
+
t = self.info()
|
|
133
|
+
host, port = t["host"], t["port"]
|
|
134
|
+
u = urllib.parse.quote(username, safe="")
|
|
135
|
+
p = urllib.parse.quote(password, safe="")
|
|
136
|
+
return {
|
|
137
|
+
"host": host,
|
|
138
|
+
"port": port,
|
|
139
|
+
"url": "%s://%s:%s@%s:%s" % (protocol, u, p, host, port),
|
|
140
|
+
"tho": "%s:%s:%s:%s" % (host, port, username, password),
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@staticmethod
|
|
144
|
+
def ref_link(ref_code, base=GOC_WEB):
|
|
145
|
+
"""Link đăng ký kèm mã giới thiệu của bạn.
|
|
146
|
+
|
|
147
|
+
IP2.ref_link("ABC123") -> https://ip2.vn/?ref=ABC123
|
|
148
|
+
"""
|
|
149
|
+
if not ref_code:
|
|
150
|
+
raise IP2Error("missing_ref", "Thiếu mã giới thiệu.", 0)
|
|
151
|
+
return "%s/?ref=%s" % (base.rstrip("/"), urllib.parse.quote(ref_code, safe=""))
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ip2vn"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "SDK chính thức của IP2.VN — điều khiển proxy xoay IP dân cư Viettel cho bên làm tool tích hợp."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "IP2.VN" }]
|
|
13
|
+
keywords = ["ip2", "ip2vn", "proxy", "rotating-proxy", "residential-proxy", "viettel", "sdk"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Topic :: Internet :: Proxy Servers",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://ip2.vn"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools]
|
|
24
|
+
py-modules = ["ip2vn"]
|
ip2vn-1.0.0/setup.cfg
ADDED