v2kit 0.2__tar.gz → 0.4__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.
- {v2kit-0.2 → v2kit-0.4}/AUTHORS.md +1 -1
- {v2kit-0.2 → v2kit-0.4}/CHANGELOG.md +20 -1
- {v2kit-0.2 → v2kit-0.4}/PKG-INFO +27 -5
- {v2kit-0.2 → v2kit-0.4}/README.md +5 -2
- {v2kit-0.2 → v2kit-0.4}/SECURITY.md +2 -2
- v2kit-0.2/dev-requirements.txt → v2kit-0.4/requirements-dev.txt +2 -0
- {v2kit-0.2 → v2kit-0.4}/setup.py +6 -16
- {v2kit-0.2 → v2kit-0.4}/tests/test_errors.py +60 -4
- {v2kit-0.2 → v2kit-0.4}/tests/test_functions.py +33 -13
- v2kit-0.4/tests/test_http.py +194 -0
- v2kit-0.4/tests/test_shadowsocks.py +196 -0
- v2kit-0.4/tests/test_socks.py +192 -0
- v2kit-0.4/tests/test_trojan.py +161 -0
- v2kit-0.4/tests/test_vless.py +169 -0
- v2kit-0.4/tests/test_vmess.py +163 -0
- {v2kit-0.2 → v2kit-0.4}/v2kit/__init__.py +8 -2
- {v2kit-0.2 → v2kit-0.4}/v2kit/functions.py +19 -1
- v2kit-0.4/v2kit/models/__init__.py +10 -0
- v2kit-0.4/v2kit/models/base.py +108 -0
- v2kit-0.4/v2kit/models/http.py +166 -0
- v2kit-0.4/v2kit/models/shadowsocks.py +168 -0
- v2kit-0.4/v2kit/models/socks.py +172 -0
- v2kit-0.4/v2kit/models/trojan.py +140 -0
- v2kit-0.4/v2kit/models/vless.py +141 -0
- v2kit-0.4/v2kit/models/vmess.py +217 -0
- {v2kit-0.2 → v2kit-0.4}/v2kit/params.py +3 -1
- {v2kit-0.2 → v2kit-0.4}/v2kit/parsers.py +43 -4
- {v2kit-0.2 → v2kit-0.4}/v2kit/utils.py +2 -3
- {v2kit-0.2 → v2kit-0.4}/v2kit/validators.py +12 -0
- {v2kit-0.2 → v2kit-0.4}/v2kit.egg-info/PKG-INFO +27 -5
- v2kit-0.4/v2kit.egg-info/SOURCES.txt +36 -0
- v2kit-0.2/requirements.txt +0 -1
- v2kit-0.2/tests/test_models.py +0 -114
- v2kit-0.2/v2kit/models.py +0 -735
- v2kit-0.2/v2kit.egg-info/SOURCES.txt +0 -25
- {v2kit-0.2 → v2kit-0.4}/LICENSE +0 -0
- {v2kit-0.2 → v2kit-0.4}/MANIFEST.in +0 -0
- {v2kit-0.2 → v2kit-0.4}/setup.cfg +0 -0
- {v2kit-0.2 → v2kit-0.4}/v2kit/__main__.py +0 -0
- {v2kit-0.2 → v2kit-0.4}/v2kit/errors.py +0 -0
- {v2kit-0.2 → v2kit-0.4}/v2kit.egg-info/dependency_links.txt +0 -0
- {v2kit-0.2 → v2kit-0.4}/v2kit.egg-info/top_level.txt +0 -0
|
@@ -5,6 +5,23 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
|
+
## [0.4] - 2026-07-02
|
|
9
|
+
### Added
|
|
10
|
+
- `HttpConfig` class
|
|
11
|
+
### Changed
|
|
12
|
+
- `parse` function modified
|
|
13
|
+
- `README.md` updated
|
|
14
|
+
- Test system modified
|
|
15
|
+
## [0.3] - 2026-06-16
|
|
16
|
+
### Added
|
|
17
|
+
- Logo
|
|
18
|
+
- `SocksConfig` class
|
|
19
|
+
- `is_socks` function
|
|
20
|
+
### Changed
|
|
21
|
+
- `README.md` updated
|
|
22
|
+
- Test system modified
|
|
23
|
+
- Dependencies structure modified
|
|
24
|
+
- All config models moved to `models` folder
|
|
8
25
|
## [0.2] - 2026-06-04
|
|
9
26
|
### Added
|
|
10
27
|
- `VMESSConfig` class
|
|
@@ -33,7 +50,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
33
50
|
- `encode_subscription` function
|
|
34
51
|
- `decode_subscription` function
|
|
35
52
|
|
|
36
|
-
[Unreleased]: https://github.com/sepandhaghighi/v2kit/compare/v0.
|
|
53
|
+
[Unreleased]: https://github.com/sepandhaghighi/v2kit/compare/v0.4...dev
|
|
54
|
+
[0.4]: https://github.com/sepandhaghighi/v2kit/compare/v0.3...v0.4
|
|
55
|
+
[0.3]: https://github.com/sepandhaghighi/v2kit/compare/v0.2...v0.3
|
|
37
56
|
[0.2]: https://github.com/sepandhaghighi/v2kit/compare/v0.1...v0.2
|
|
38
57
|
[0.1]: https://github.com/sepandhaghighi/v2kit/compare/bb5a2cb...v0.1
|
|
39
58
|
|
{v2kit-0.2 → v2kit-0.4}/PKG-INFO
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: v2kit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4
|
|
4
4
|
Summary: V2Kit: A Lightweight Toolkit for V2Ray Config Manipulation
|
|
5
5
|
Home-page: https://github.com/sepandhaghighi/v2kit
|
|
6
|
-
Download-URL: https://github.com/sepandhaghighi/v2kit/tarball/v0.
|
|
6
|
+
Download-URL: https://github.com/sepandhaghighi/v2kit/tarball/v0.4
|
|
7
7
|
Author: Sepand Haghighi
|
|
8
8
|
Author-email: me@sepand.tech
|
|
9
9
|
License: MIT
|
|
@@ -44,6 +44,7 @@ Dynamic: summary
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div align="center">
|
|
47
|
+
<img src="https://github.com/sepandhaghighi/v2kit/raw/main/otherfiles/logo.png" width="350">
|
|
47
48
|
<h1>V2Kit: A Lightweight Toolkit for V2Ray Config Manipulation</h1>
|
|
48
49
|
<br/>
|
|
49
50
|
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/built%20with-Python3-green.svg" alt="built with Python3"></a>
|
|
@@ -95,13 +96,13 @@ V2Kit is a lightweight and extensible Python toolkit for working with V2Ray prox
|
|
|
95
96
|
## Installation
|
|
96
97
|
|
|
97
98
|
### Source Code
|
|
98
|
-
- Download [Version 0.
|
|
99
|
+
- Download [Version 0.4](https://github.com/sepandhaghighi/v2kit/archive/v0.4.zip) or [Latest Source](https://github.com/sepandhaghighi/v2kit/archive/dev.zip)
|
|
99
100
|
- `pip install .`
|
|
100
101
|
|
|
101
102
|
### PyPI
|
|
102
103
|
|
|
103
104
|
- Check [Python Packaging User Guide](https://packaging.python.org/installing/)
|
|
104
|
-
- `pip install v2kit==0.
|
|
105
|
+
- `pip install v2kit==0.4`
|
|
105
106
|
|
|
106
107
|
## Supported Protocols
|
|
107
108
|
|
|
@@ -113,6 +114,8 @@ V2Kit currently supports the following protocols:
|
|
|
113
114
|
| VLESS | ✅ | ✅ | ✅ | ✅ |
|
|
114
115
|
| Trojan | ✅ | ✅ | ✅ | ✅ |
|
|
115
116
|
| Shadowsocks | ✅ | ✅ | ✅ | ✅ |
|
|
117
|
+
| SOCKS | ✅ | ✅ | ✅ | ✅ |
|
|
118
|
+
| HTTP | ✅ | ✅ | ✅ | ✅ |
|
|
116
119
|
|
|
117
120
|
|
|
118
121
|
## Usage
|
|
@@ -208,6 +211,23 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
|
208
211
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
209
212
|
|
|
210
213
|
## [Unreleased]
|
|
214
|
+
## [0.4] - 2026-07-02
|
|
215
|
+
### Added
|
|
216
|
+
- `HttpConfig` class
|
|
217
|
+
### Changed
|
|
218
|
+
- `parse` function modified
|
|
219
|
+
- `README.md` updated
|
|
220
|
+
- Test system modified
|
|
221
|
+
## [0.3] - 2026-06-16
|
|
222
|
+
### Added
|
|
223
|
+
- Logo
|
|
224
|
+
- `SocksConfig` class
|
|
225
|
+
- `is_socks` function
|
|
226
|
+
### Changed
|
|
227
|
+
- `README.md` updated
|
|
228
|
+
- Test system modified
|
|
229
|
+
- Dependencies structure modified
|
|
230
|
+
- All config models moved to `models` folder
|
|
211
231
|
## [0.2] - 2026-06-04
|
|
212
232
|
### Added
|
|
213
233
|
- `VMESSConfig` class
|
|
@@ -236,7 +256,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
236
256
|
- `encode_subscription` function
|
|
237
257
|
- `decode_subscription` function
|
|
238
258
|
|
|
239
|
-
[Unreleased]: https://github.com/sepandhaghighi/v2kit/compare/v0.
|
|
259
|
+
[Unreleased]: https://github.com/sepandhaghighi/v2kit/compare/v0.4...dev
|
|
260
|
+
[0.4]: https://github.com/sepandhaghighi/v2kit/compare/v0.3...v0.4
|
|
261
|
+
[0.3]: https://github.com/sepandhaghighi/v2kit/compare/v0.2...v0.3
|
|
240
262
|
[0.2]: https://github.com/sepandhaghighi/v2kit/compare/v0.1...v0.2
|
|
241
263
|
[0.1]: https://github.com/sepandhaghighi/v2kit/compare/bb5a2cb...v0.1
|
|
242
264
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
+
<img src="https://github.com/sepandhaghighi/v2kit/raw/main/otherfiles/logo.png" width="350">
|
|
2
3
|
<h1>V2Kit: A Lightweight Toolkit for V2Ray Config Manipulation</h1>
|
|
3
4
|
<br/>
|
|
4
5
|
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/built%20with-Python3-green.svg" alt="built with Python3"></a>
|
|
@@ -50,13 +51,13 @@ V2Kit is a lightweight and extensible Python toolkit for working with V2Ray prox
|
|
|
50
51
|
## Installation
|
|
51
52
|
|
|
52
53
|
### Source Code
|
|
53
|
-
- Download [Version 0.
|
|
54
|
+
- Download [Version 0.4](https://github.com/sepandhaghighi/v2kit/archive/v0.4.zip) or [Latest Source](https://github.com/sepandhaghighi/v2kit/archive/dev.zip)
|
|
54
55
|
- `pip install .`
|
|
55
56
|
|
|
56
57
|
### PyPI
|
|
57
58
|
|
|
58
59
|
- Check [Python Packaging User Guide](https://packaging.python.org/installing/)
|
|
59
|
-
- `pip install v2kit==0.
|
|
60
|
+
- `pip install v2kit==0.4`
|
|
60
61
|
|
|
61
62
|
## Supported Protocols
|
|
62
63
|
|
|
@@ -68,6 +69,8 @@ V2Kit currently supports the following protocols:
|
|
|
68
69
|
| VLESS | ✅ | ✅ | ✅ | ✅ |
|
|
69
70
|
| Trojan | ✅ | ✅ | ✅ | ✅ |
|
|
70
71
|
| Shadowsocks | ✅ | ✅ | ✅ | ✅ |
|
|
72
|
+
| SOCKS | ✅ | ✅ | ✅ | ✅ |
|
|
73
|
+
| HTTP | ✅ | ✅ | ✅ | ✅ |
|
|
71
74
|
|
|
72
75
|
|
|
73
76
|
## Usage
|
{v2kit-0.2 → v2kit-0.4}/setup.py
RENAMED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
"""Setup module."""
|
|
3
|
-
from
|
|
4
|
-
try:
|
|
5
|
-
from setuptools import setup
|
|
6
|
-
except ImportError:
|
|
7
|
-
from distutils.core import setup
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def get_requires() -> List[str]:
|
|
11
|
-
"""Read requirements.txt."""
|
|
12
|
-
requirements = open("requirements.txt", "r").read()
|
|
13
|
-
return list(filter(lambda x: x != "", requirements.split()))
|
|
3
|
+
from setuptools import setup
|
|
14
4
|
|
|
15
5
|
|
|
16
6
|
def read_description() -> str:
|
|
@@ -32,8 +22,8 @@ def read_description() -> str:
|
|
|
32
22
|
|
|
33
23
|
setup(
|
|
34
24
|
name='v2kit',
|
|
35
|
-
packages=['v2kit'],
|
|
36
|
-
version='0.
|
|
25
|
+
packages=['v2kit', 'v2kit.models'],
|
|
26
|
+
version='0.4',
|
|
37
27
|
description='V2Kit: A Lightweight Toolkit for V2Ray Config Manipulation',
|
|
38
28
|
long_description=read_description(),
|
|
39
29
|
long_description_content_type='text/markdown',
|
|
@@ -41,11 +31,11 @@ setup(
|
|
|
41
31
|
author='Sepand Haghighi',
|
|
42
32
|
author_email='me@sepand.tech',
|
|
43
33
|
url='https://github.com/sepandhaghighi/v2kit',
|
|
44
|
-
download_url='https://github.com/sepandhaghighi/v2kit/tarball/v0.
|
|
45
|
-
keywords=
|
|
34
|
+
download_url='https://github.com/sepandhaghighi/v2kit/tarball/v0.4',
|
|
35
|
+
keywords='v2ray v2ray-config v2ray-tools vmess vless trojan shadowsocks proxy subscription network',
|
|
46
36
|
project_urls={
|
|
47
37
|
'Source': 'https://github.com/sepandhaghighi/v2kit'},
|
|
48
|
-
install_requires=
|
|
38
|
+
install_requires=[],
|
|
49
39
|
python_requires='>=3.8',
|
|
50
40
|
classifiers=[
|
|
51
41
|
'Development Status :: 3 - Alpha',
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
-
from v2kit import VMESSConfig, VLESSConfig, TrojanConfig, ShadowsocksConfig
|
|
4
|
+
from v2kit import VMESSConfig, VLESSConfig, TrojanConfig, ShadowsocksConfig, SocksConfig
|
|
5
5
|
from v2kit import relabel, encode_subscription, decode_subscription, parse
|
|
6
6
|
from v2kit import V2kitError, V2kitValidationError, V2kitParseError
|
|
7
7
|
from v2kit.validators import _validate_uri
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
INVALID_PROTOCOL = "
|
|
10
|
+
INVALID_PROTOCOL = "ftp://example.com"
|
|
11
11
|
|
|
12
12
|
INVALID_VMESS = "vmess://invalid-base64"
|
|
13
13
|
|
|
14
|
+
INVALID_SHADOWSOCKS = "ss://invalid-base64@example.com:8388#ss-test"
|
|
15
|
+
|
|
14
16
|
VALID_VLESS = (
|
|
15
17
|
"vless://1c4b4bca-e3ff-4ca8-a062-6f399ad3cf45@example.com:443"
|
|
16
18
|
"?security=tls#test"
|
|
@@ -61,7 +63,7 @@ def test_relabel_non_string_label():
|
|
|
61
63
|
relabel(VALID_VLESS, 123)
|
|
62
64
|
|
|
63
65
|
|
|
64
|
-
def
|
|
66
|
+
def test_encode_subscription_invalid_config1():
|
|
65
67
|
configs = [
|
|
66
68
|
VALID_VLESS,
|
|
67
69
|
"invalid-config",
|
|
@@ -71,6 +73,16 @@ def test_encode_subscription_invalid_config():
|
|
|
71
73
|
encode_subscription(configs)
|
|
72
74
|
|
|
73
75
|
|
|
76
|
+
def test_encode_subscription_invalid_config2():
|
|
77
|
+
configs = [
|
|
78
|
+
VALID_VLESS,
|
|
79
|
+
1,
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
with pytest.raises(V2kitValidationError):
|
|
83
|
+
encode_subscription(configs)
|
|
84
|
+
|
|
85
|
+
|
|
74
86
|
def test_decode_subscription_non_string():
|
|
75
87
|
with pytest.raises(V2kitValidationError):
|
|
76
88
|
decode_subscription(123)
|
|
@@ -109,7 +121,17 @@ def test_parse_invalid_uri():
|
|
|
109
121
|
|
|
110
122
|
def test_parse_unsupported_protocol():
|
|
111
123
|
with pytest.raises(V2kitParseError):
|
|
112
|
-
parse(
|
|
124
|
+
parse(INVALID_PROTOCOL)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def test_parse_invalid_vmess():
|
|
128
|
+
with pytest.raises(V2kitParseError):
|
|
129
|
+
parse(INVALID_VMESS)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_parse_invalid_shadowsocks():
|
|
133
|
+
with pytest.raises(V2kitParseError):
|
|
134
|
+
parse(INVALID_SHADOWSOCKS)
|
|
113
135
|
|
|
114
136
|
|
|
115
137
|
def test_vless_invalid_uuid():
|
|
@@ -166,3 +188,37 @@ def test_shadowsocks_empty_encryption():
|
|
|
166
188
|
address="example.com",
|
|
167
189
|
port=8388,
|
|
168
190
|
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def test_socks_invalid_port():
|
|
194
|
+
with pytest.raises(V2kitValidationError):
|
|
195
|
+
SocksConfig(
|
|
196
|
+
address="example.com",
|
|
197
|
+
port=70000,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def test_socks_empty_address():
|
|
202
|
+
with pytest.raises(V2kitValidationError):
|
|
203
|
+
SocksConfig(
|
|
204
|
+
address="",
|
|
205
|
+
port=1080,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def test_socks_invalid_username():
|
|
210
|
+
with pytest.raises(V2kitValidationError):
|
|
211
|
+
SocksConfig(
|
|
212
|
+
address="example.com",
|
|
213
|
+
port=1080,
|
|
214
|
+
username="",
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def test_socks_invalid_password():
|
|
219
|
+
with pytest.raises(V2kitValidationError):
|
|
220
|
+
SocksConfig(
|
|
221
|
+
address="example.com",
|
|
222
|
+
port=1080,
|
|
223
|
+
password="",
|
|
224
|
+
)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from v2kit import is_vmess, is_vless, is_trojan, is_shadowsocks, parse
|
|
4
|
+
from v2kit import is_vmess, is_vless, is_trojan, is_shadowsocks, is_socks, is_http, parse
|
|
5
5
|
from v2kit import relabel, encode_subscription, decode_subscription
|
|
6
|
-
from v2kit import VMESSConfig, VLESSConfig, TrojanConfig, ShadowsocksConfig
|
|
6
|
+
from v2kit import VMESSConfig, VLESSConfig, TrojanConfig, ShadowsocksConfig, SocksConfig
|
|
7
7
|
from v2kit.utils import _encode_base64
|
|
8
8
|
|
|
9
9
|
|
|
@@ -29,19 +29,15 @@ def create_vmess(label="test"):
|
|
|
29
29
|
|
|
30
30
|
VMESS_CONFIG = create_vmess()
|
|
31
31
|
|
|
32
|
-
VLESS_CONFIG =
|
|
33
|
-
"vless://1c4b4bca-e3ff-4ca8-a062-6f399ad3cf45@example.com:443"
|
|
34
|
-
"?security=tls#vless-test"
|
|
35
|
-
)
|
|
32
|
+
VLESS_CONFIG = "vless://1c4b4bca-e3ff-4ca8-a062-6f399ad3cf45@example.com:443?security=tls#vless-test"
|
|
36
33
|
|
|
37
|
-
TROJAN_CONFIG =
|
|
38
|
-
"trojan://password@example.com:443"
|
|
39
|
-
"?security=tls#trojan-test"
|
|
40
|
-
)
|
|
34
|
+
TROJAN_CONFIG = "trojan://password@example.com:443?security=tls#trojan-test"
|
|
41
35
|
|
|
42
|
-
SHADOWSOCKS_CONFIG =
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
SHADOWSOCKS_CONFIG = "ss://YWVzLTI1Ni1nY206cGFzc3dvcmQ=@example.com:8388#ss-test"
|
|
37
|
+
|
|
38
|
+
SOCKS_CONFIG = "socks://user:password@example.com:1080#socks-test"
|
|
39
|
+
|
|
40
|
+
HTTP_CONFIG = "http://user@example.com:1080#test"
|
|
45
41
|
|
|
46
42
|
|
|
47
43
|
def test_is_vmess():
|
|
@@ -60,6 +56,10 @@ def test_is_shadowsocks():
|
|
|
60
56
|
assert is_shadowsocks(SHADOWSOCKS_CONFIG) is True
|
|
61
57
|
|
|
62
58
|
|
|
59
|
+
def test_is_http():
|
|
60
|
+
assert is_http(HTTP_CONFIG) is True
|
|
61
|
+
|
|
62
|
+
|
|
63
63
|
def test_is_vmess_negative():
|
|
64
64
|
assert is_vmess(VLESS_CONFIG) is False
|
|
65
65
|
|
|
@@ -80,6 +80,18 @@ def test_is_shadowsocks_invalid():
|
|
|
80
80
|
assert is_shadowsocks("invalid") is False
|
|
81
81
|
|
|
82
82
|
|
|
83
|
+
def test_is_http_invalid():
|
|
84
|
+
assert is_http("invalid") is False
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_is_socks():
|
|
88
|
+
assert is_socks(SOCKS_CONFIG) is True
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_is_socks_invalid():
|
|
92
|
+
assert is_socks("invalid") is False
|
|
93
|
+
|
|
94
|
+
|
|
83
95
|
def test_relabel_vmess():
|
|
84
96
|
result = relabel(VMESS_CONFIG, "new-label")
|
|
85
97
|
|
|
@@ -142,6 +154,7 @@ def test_encode_decode_subscription_roundtrip():
|
|
|
142
154
|
VLESS_CONFIG,
|
|
143
155
|
TROJAN_CONFIG,
|
|
144
156
|
SHADOWSOCKS_CONFIG,
|
|
157
|
+
SOCKS_CONFIG,
|
|
145
158
|
]
|
|
146
159
|
|
|
147
160
|
encoded = encode_subscription(configs)
|
|
@@ -206,3 +219,10 @@ def test_parse_shadowsocks():
|
|
|
206
219
|
parse(SHADOWSOCKS_CONFIG),
|
|
207
220
|
ShadowsocksConfig,
|
|
208
221
|
)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def test_parse_socks():
|
|
225
|
+
assert isinstance(
|
|
226
|
+
parse(SOCKS_CONFIG),
|
|
227
|
+
SocksConfig,
|
|
228
|
+
)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import pytest
|
|
3
|
+
from v2kit import parse
|
|
4
|
+
from v2kit import HttpConfig
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_defaults():
|
|
8
|
+
config = HttpConfig(
|
|
9
|
+
address="example.com",
|
|
10
|
+
port=1080,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
assert config.label is None
|
|
14
|
+
assert config.extra == {}
|
|
15
|
+
assert config.username is None
|
|
16
|
+
assert config.password is None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_to_dict():
|
|
20
|
+
config = HttpConfig(
|
|
21
|
+
address="example.com",
|
|
22
|
+
port=1080,
|
|
23
|
+
username="user",
|
|
24
|
+
password="password",
|
|
25
|
+
label="test",
|
|
26
|
+
extra={"foo": "bar"},
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
assert config.to_dict() == {
|
|
30
|
+
"protocol": "http",
|
|
31
|
+
"address": "example.com",
|
|
32
|
+
"port": 1080,
|
|
33
|
+
"username": "user",
|
|
34
|
+
"password": "password",
|
|
35
|
+
"extra": {"foo": "bar"},
|
|
36
|
+
"label": "test",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_extra():
|
|
41
|
+
config = HttpConfig(
|
|
42
|
+
address="example.com",
|
|
43
|
+
port=1080,
|
|
44
|
+
extra={"foo": "bar"},
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
data = config.to_dict()
|
|
48
|
+
|
|
49
|
+
assert data["extra"]["foo"] == "bar"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_update_methods():
|
|
53
|
+
config = HttpConfig(
|
|
54
|
+
address="example.com",
|
|
55
|
+
port=1080,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
config.update_address("example.org")
|
|
59
|
+
config.update_port(8080)
|
|
60
|
+
config.update_username("user")
|
|
61
|
+
config.update_password("password")
|
|
62
|
+
|
|
63
|
+
assert config.address == "example.org"
|
|
64
|
+
assert config.port == 8080
|
|
65
|
+
assert config.username == "user"
|
|
66
|
+
assert config.password == "password"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_update_extra():
|
|
70
|
+
config = HttpConfig(
|
|
71
|
+
address="example.com",
|
|
72
|
+
port=1080,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
config.update_extra(
|
|
76
|
+
{"foo": "bar"}
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
assert config.extra["foo"] == "bar"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_method_chaining():
|
|
83
|
+
config = HttpConfig(
|
|
84
|
+
address="example.com",
|
|
85
|
+
port=1080,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
config.update_address(
|
|
89
|
+
"example.org"
|
|
90
|
+
).update_port(
|
|
91
|
+
8080
|
|
92
|
+
).update_username(
|
|
93
|
+
"user"
|
|
94
|
+
).update_password(
|
|
95
|
+
"password"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
assert config.address == "example.org"
|
|
99
|
+
assert config.port == 8080
|
|
100
|
+
assert config.username == "user"
|
|
101
|
+
assert config.password == "password"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@pytest.mark.parametrize(
|
|
105
|
+
"kwargs",
|
|
106
|
+
[
|
|
107
|
+
{"address": ""},
|
|
108
|
+
{"port": 0},
|
|
109
|
+
{"port": 1.2},
|
|
110
|
+
{"username": ""},
|
|
111
|
+
{"password": ""},
|
|
112
|
+
{"extra": 1},
|
|
113
|
+
],
|
|
114
|
+
)
|
|
115
|
+
def test_invalid_values(kwargs):
|
|
116
|
+
params = {
|
|
117
|
+
"address": "example.com",
|
|
118
|
+
"port": 1080,
|
|
119
|
+
}
|
|
120
|
+
params.update(kwargs)
|
|
121
|
+
|
|
122
|
+
with pytest.raises(ValueError):
|
|
123
|
+
HttpConfig(**params)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_to_uri_roundtrip():
|
|
127
|
+
config = HttpConfig(
|
|
128
|
+
address="example.com",
|
|
129
|
+
port=1080,
|
|
130
|
+
username="user",
|
|
131
|
+
password="password",
|
|
132
|
+
label="test",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
parsed = parse(config.to_uri())
|
|
136
|
+
|
|
137
|
+
assert parsed == config
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_equality():
|
|
141
|
+
config1 = HttpConfig(
|
|
142
|
+
address="example.com",
|
|
143
|
+
port=1080,
|
|
144
|
+
username="user",
|
|
145
|
+
password="password",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
config2 = HttpConfig(
|
|
149
|
+
address="example.com",
|
|
150
|
+
port=1080,
|
|
151
|
+
username="user",
|
|
152
|
+
password="password",
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
config3 = HttpConfig(
|
|
156
|
+
address="example.org",
|
|
157
|
+
port=1080,
|
|
158
|
+
username="user",
|
|
159
|
+
password="password",
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
assert config1 == config2
|
|
163
|
+
assert config1 != config3
|
|
164
|
+
assert config1 != "config1"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_to_uri_without_auth():
|
|
168
|
+
config = HttpConfig(
|
|
169
|
+
address="example.com",
|
|
170
|
+
port=1080,
|
|
171
|
+
label="test",
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
assert config.to_uri() == "http://example.com:1080#test"
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def test_to_uri_username_only():
|
|
178
|
+
config = HttpConfig(
|
|
179
|
+
address="example.com",
|
|
180
|
+
port=1080,
|
|
181
|
+
username="user",
|
|
182
|
+
label="test",
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
assert config.to_uri() == "http://user@example.com:1080#test"
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def test_repr():
|
|
189
|
+
config = HttpConfig(
|
|
190
|
+
address="example.com",
|
|
191
|
+
port=1080,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
assert repr(config) == "HttpConfig(protocol=<Protocol.HTTP: 'http'>, label=None)"
|