Skip to content

Commit d83ec1a

Browse files
Add files via upload
1 parent 4523622 commit d83ec1a

File tree

3 files changed

+157
-116
lines changed

3 files changed

+157
-116
lines changed

examples/01_simple_start_stop.py

Lines changed: 67 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,82 @@
11
# examples/01_simple_start_stop.py
22

33
import time
4-
import os
5-
import sys
6-
7-
# * This is a clever way to make the script find our library
8-
# * without having to install it first.
9-
# * It adds the parent directory (the project root) to Python's path.
10-
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
4+
from pathlib import Path
115

6+
from python_v2ray.downloader import BinaryDownloader
7+
from python_v2ray.config_parser import XrayConfigBuilder, parse_uri
128
from python_v2ray.core import XrayCore
139

1410
def main():
15-
"""
16-
* A simple demonstration of starting and stopping the Xray core.
17-
"""
18-
# note: Define paths relative to the project root.
19-
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
20-
xray_path = os.path.join(project_root, "vendor", "xray.exe") # ? On Linux/Mac, this would be just "xray"
21-
config_path = os.path.join(project_root, "config.json")
2211

23-
print(f"note: Using Xray executable at: {xray_path}")
24-
print(f"note: Using config file at: {config_path}")
12+
print("--- Python-V2Ray Simple Start/Stop Example ---")
13+
14+
15+
project_root = Path(__file__).parent.parent
16+
vendor_dir = project_root / "vendor"
17+
18+
print(f"Project root detected at: {project_root}")
19+
print(f"Vendor directory set to: {vendor_dir}")
20+
21+
22+
try:
23+
downloader = BinaryDownloader(project_root)
24+
downloader.ensure_all()
25+
except Exception as e:
26+
print(f"\n! FATAL: {e}")
27+
return
28+
29+
30+
sample_vless_uri = "trojan://2ee85121-31de-4581-a492-eb00f606e392@198.46.152.83:443?mux=&security=tls&headerType=none&type=tcp&muxConcurrency=-1&sni=sj3.freeguard.org#trojan:4349S"
31+
32+
params = parse_uri(sample_vless_uri)
33+
if not params:
34+
print("! Failed to parse the sample URI. Exiting.")
35+
return
36+
37+
builder = XrayConfigBuilder()
38+
39+
local_socks_port = 10808
40+
builder.add_inbound({
41+
"port": local_socks_port,
42+
"listen": "127.0.0.1",
43+
"protocol": "socks",
44+
"settings": {
45+
"auth": "noauth",
46+
"udp": True,
47+
"ip": "127.0.0.1"
48+
},
49+
"tag": "socks_in"
50+
})
51+
52+
outbound_config = builder.build_outbound_from_params(params)
53+
builder.add_outbound(outbound_config)
54+
55+
builder.config["routing"]["rules"].append({
56+
"type": "field",
57+
"inboundTag": ["socks_in"],
58+
"outboundTag": outbound_config["tag"]
59+
})
60+
61+
print(f"* Configuration created. SOCKS proxy will be available at 127.0.0.1:{local_socks_port}")
2562

2663
try:
27-
# Create an instance of our core controller
28-
xray = XrayCore(executable_path=xray_path, config_path=config_path)
29-
30-
# Start the core
31-
xray.start()
32-
33-
if xray.is_running():
34-
print("\n* Xray is running. You can check your Task Manager.")
35-
print("* Waiting for 10 seconds before stopping...")
36-
time.sleep(10)
37-
else:
38-
print("\n! Xray failed to start. Check the paths and permissions.")
39-
return
40-
41-
# Stop the core
42-
xray.stop()
43-
print("\n* Demo finished.")
44-
45-
except FileNotFoundError as e:
46-
print(f"\n! ERROR: A required file was not found.")
47-
print(f"! {e}")
48-
print("! Please make sure you have downloaded the Xray core into the 'vendor' folder.")
64+
65+
with XrayCore(vendor_dir=str(vendor_dir), config_builder=builder, debug_mode=True) as xray_process:
66+
if xray_process.is_running():
67+
print(f"* Xray core is running with PID: {xray_process.process.pid}")
68+
print("* The process will run for 15 seconds before shutting down.")
69+
print("* You can now configure an application (e.g., a web browser) to use the SOCKS proxy.")
70+
time.sleep(15)
71+
else:
72+
print("! Failed to start the Xray core process.")
73+
74+
except FileNotFoundError:
75+
print("! Error: Could not find the Xray executable. Please check the vendor path.")
4976
except Exception as e:
50-
print(f"\n! An unexpected error occurred: {e}")
77+
print(f"! An unexpected error occurred: {e}")
5178

79+
print("--- Example finished ---")
5280

5381
if __name__ == "__main__":
5482
main()

examples/02_config_builder.py

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,65 @@
11
# examples/02_config_builder.py
22

33
import time
4-
import os
5-
import sys
4+
from pathlib import Path
65
import json
76

8-
# * This ensures the script can find our local library files
9-
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
107

8+
from python_v2ray.downloader import BinaryDownloader
119
from python_v2ray.core import XrayCore
1210
from python_v2ray.config_parser import parse_uri, XrayConfigBuilder
1311

14-
def run_test_with_uri(xray_path: str, uri: str):
12+
def run_test_with_uri(vendor_dir: Path, uri: str):
1513
"""
16-
* A helper function to test a single URI from start to finish.
14+
A helper function to test a single URI from start to finish.
15+
It builds a config, runs Xray, waits, and then stops.
1716
"""
1817
print("\n" + "="*60)
1918
print(f"* Testing URI: {uri[:50]}...")
2019
print("="*60)
2120

21+
# Step A: Parse the URI
2222
params = parse_uri(uri)
2323
if not params:
2424
print("! TEST FAILED: Could not parse the URI.")
2525
return
2626

2727
print(f"* PARSING SUCCESS: Protocol='{params.protocol}', Address='{params.address}:{params.port}'")
28-
# print(f"* Full Params: {params}") # note: Uncomment for deep debugging
2928

29+
# Step B: Build the configuration
3030
print("\n* Building full Xray config...")
3131
builder = XrayConfigBuilder()
3232

33-
# * Add a local SOCKS inbound for our apps to connect to
33+
# Add inbound with a specific tag
3434
builder.add_inbound({
3535
"port": 10808, "listen": "127.0.0.1", "protocol": "socks",
36-
"settings": {"auth": "noauth", "udp": True}
36+
"settings": {"auth": "noauth", "udp": True},
37+
"tag": "socks_in" # Add a tag to reference in routing
3738
})
3839

39-
# * Build the outbound using our powerful engine
40+
# Build and add outbound
4041
outbound_dict = builder.build_outbound_from_params(params)
4142
builder.add_outbound(outbound_dict)
4243

43-
# * Add default direct and block outbounds (good practice)
44-
builder.add_outbound({"protocol": "freedom", "tag": "direct"})
45-
builder.add_outbound({"protocol": "blackhole", "tag": "block"})
44+
# Add a routing rule to connect inbound to outbound
45+
builder.config["routing"]["rules"].append({
46+
"type": "field",
47+
"inboundTag": ["socks_in"],
48+
"outboundTag": outbound_dict["tag"]
49+
})
4650

47-
print("\n* Final JSON config generated:")
48-
print(builder.to_json())
51+
print("* Final JSON config generated:")
4952

53+
print(json.dumps(builder.config, indent=2))
5054

55+
# Step C: Run Xray with the generated config
5156
print("\n* Attempting to start Xray core...")
5257
try:
53-
with XrayCore(executable_path=xray_path, config_builder=builder) as xray:
58+
with XrayCore(vendor_dir=str(vendor_dir), config_builder=builder) as xray:
5459
if xray.is_running():
5560
print("\n* SUCCESS! Xray is running with this config.")
5661
print("* Local SOCKS proxy is available on 127.0.0.1:10808")
57-
print("* Running for 5 seconds...")
62+
print("* Running for 5 seconds before next test...")
5863
time.sleep(5)
5964
else:
6065
print("\n! TEST FAILED: Xray did not start.")
@@ -66,18 +71,22 @@ def run_test_with_uri(xray_path: str, uri: str):
6671

6772
def main():
6873
"""
69-
* Runs a series of tests with different URI types.
74+
Runs a series of tests with a list of different URI types.
7075
"""
71-
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
72-
xray_path = os.path.join(project_root, "vendor", "xray.exe") # ? On Linux/Mac, this would be "xray"
76+
project_root = Path(__file__).parent.parent
77+
vendor_dir = project_root / "vendor"
7378

74-
if not os.path.exists(xray_path):
75-
print(f"! FATAL ERROR: Xray executable not found at '{xray_path}'")
76-
print("! Please download it and place it in the 'vendor' folder.")
79+
print("--- Running Python-V2Ray Batch URI Tester ---")
80+
print(f"Vendor directory set to: {vendor_dir}")
81+
try:
82+
downloader = BinaryDownloader(project_root)
83+
downloader.ensure_all()
84+
except Exception as e:
85+
print(f"\n! FATAL: {e}")
7786
return
7887

7988
# ! =======================================================================
80-
# ! === REPLACE THESE WITH YOUR OWN REAL TEST URIS ===
89+
# ! === REPLACE THESE WITH A REAL TEST URI ===
8190
# ! =======================================================================
8291
test_uris = [
8392
"vless://YOUR_UUID@your.domain.com:443?security=tls&sni=your.domain.com&fp=chrome&type=ws&path=%2F#VLESS-WS-TLS",
@@ -86,12 +95,11 @@ def main():
8695
"ss://YWVzLTI1Ni1nY206eW91cl9wYXNzd29yZA==@your.domain.com:8443#ShadowSocks-Test"
8796
]
8897

98+
8999
for uri in test_uris:
90-
if "YOUR_" in uri:
91-
print(f"\n! Skipping placeholder URI: {uri[:50]}...")
92-
print("! Please replace it with your own real config URI in the 'test_uris' list to test it.")
100+
if "YOUR_" in uri or "your.domain.com" in uri:
93101
continue
94-
run_test_with_uri(xray_path, uri)
102+
run_test_with_uri(vendor_dir, uri)
95103

96104

97105
if __name__ == "__main__":

examples/03_stats_viewer.py

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,43 @@
1+
2+
3+
4+
15
# examples/03_stats_viewer.py
26

37
import time
4-
import os
5-
import sys
6-
7-
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
8+
from pathlib import Path
89

10+
from python_v2ray.downloader import BinaryDownloader
911
from python_v2ray.core import XrayCore
1012
from python_v2ray.config_parser import parse_uri, XrayConfigBuilder
1113

1214
def main():
1315
"""
1416
* Demonstrates how to run Xray with the API enabled and fetch live stats.
17+
* This version uses the ORIGINAL printing logic.
1518
"""
16-
# ! Replace with your own REAL and WORKING VLESS URI
17-
vless_uri = "vless://"
1819

19-
if "YOUR_UUID" in vless_uri:
20-
print("! Please replace the placeholder URI in the script with your own to run this demo.")
20+
project_root = Path(__file__).parent.parent
21+
vendor_dir = project_root / "vendor"
22+
try:
23+
downloader = BinaryDownloader(project_root)
24+
downloader.ensure_all()
25+
except Exception as e:
26+
print(f"\n! FATAL: {e}")
2127
return
28+
test_uri = "vless://"
2229

23-
params = parse_uri(vless_uri)
30+
params = parse_uri(test_uri)
2431
if not params:
2532
return
2633

27-
# * The tag of our main outbound that we want to monitor
28-
params.tag = "proxy"
2934
outbound_tag_to_monitor = "proxy"
30-
31-
# * The port for the gRPC API
35+
params.tag = outbound_tag_to_monitor
3236
api_port = 62789
3337

34-
print(f"* Building config to monitor outbound with tag: '{outbound_tag_to_monitor}'")
3538
builder = XrayConfigBuilder()
36-
builder.enable_api(port=api_port) # ! Enable the API service
39+
builder.enable_api(port=api_port)
40+
3741
builder.add_inbound({
3842
"port": 10808,
3943
"listen": "127.0.0.1",
@@ -48,40 +52,41 @@ def main():
4852
outbound = builder.build_outbound_from_params(params)
4953
builder.add_outbound(outbound)
5054
builder.add_outbound({"protocol": "freedom", "tag": "direct"})
51-
print("\n" + "="*20 + " FINAL CONFIG TO BE USED " + "="*20)
52-
final_config_json = builder.to_json()
53-
print(final_config_json)
54-
print("="*61 + "\n")
55-
56-
57-
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
58-
xray_path = os.path.join(project_root, "vendor", "xray.exe")
59-
60-
print("* Starting Xray with API enabled...")
61-
# ! Pass the api_port to the XrayCore constructor
62-
with XrayCore(executable_path=xray_path, config_builder=builder, api_port=api_port) as xray:
63-
if not xray.is_running():
64-
print("! Xray failed to start.")
65-
return
66-
67-
print("\n* Xray is running. SOCKS on 10808. API on 62789.")
68-
print("* Now, generate some traffic through the SOCKS proxy (e.g., watch a video, run a speed test).")
69-
print("* Press Ctrl+C to stop.\n")
70-
71-
try:
72-
while True:
73-
time.sleep(2)
74-
stats = xray.get_stats(tag=outbound_tag_to_monitor)
75-
if stats:
76-
uplink_mb = stats['uplink'] / (1024 * 1024)
77-
downlink_mb = stats['downlink'] / (1024 * 1024)
78-
print(f"* Live Stats for '{outbound_tag_to_monitor}': Uplink: {uplink_mb:.2f} MB | Downlink: {downlink_mb:.2f} MB")
79-
else:
80-
print(f"\r* Waiting for traffic on tag '{outbound_tag_to_monitor}'...", end="")
81-
except KeyboardInterrupt:
82-
print("\n* User stopped the stats viewer.")
83-
84-
print("* Demo finished.")
55+
56+
57+
builder.config["routing"]["rules"].append({
58+
"type": "field",
59+
"inboundTag": ["socks_in"],
60+
"outboundTag": outbound_tag_to_monitor
61+
})
62+
63+
try:
64+
with XrayCore(vendor_dir=str(vendor_dir), config_builder=builder, api_port=api_port) as xray:
65+
if not xray.is_running():
66+
print("! Xray failed to start.")
67+
return
68+
69+
print(f"\n* Xray is running. SOCKS on 10808. API on {api_port}.")
70+
print("* Generate some traffic through the SOCKS proxy.")
71+
print("* Press Ctrl+C to stop.\n")
72+
73+
try:
74+
while True:
75+
time.sleep(2)
76+
stats = xray.get_stats(tag=outbound_tag_to_monitor)
77+
if stats:
78+
uplink_mb = stats['uplink'] / (1024 * 1024)
79+
downlink_mb = stats['downlink'] / (1024 * 1024)
80+
print(f"* Live Stats for '{outbound_tag_to_monitor}': Uplink: {uplink_mb:.2f} MB | Downlink: {downlink_mb:.2f} MB")
81+
else:
82+
print(f"\r* Waiting for traffic on tag '{outbound_tag_to_monitor}'...", end="")
83+
except KeyboardInterrupt:
84+
print("\n* User stopped the stats viewer.")
85+
86+
except Exception as e:
87+
print(f"\n! An error occurred: {e}")
88+
89+
print("\n* Demo finished.")
8590

8691
if __name__ == "__main__":
8792
main()

0 commit comments

Comments
 (0)