Skip to content

Commit

Permalink
Merge pull request #2 from wikm360/dev
Browse files Browse the repository at this point in the history
V4
  • Loading branch information
wikm360 authored Oct 14, 2024
2 parents 42e06bd + 4e44ff0 commit 7b4ce7f
Show file tree
Hide file tree
Showing 14 changed files with 780 additions and 2 deletions.
181 changes: 181 additions & 0 deletions .github/workflows/desktop-builds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
name: Build and Release Executable

on:
push:
branches:
- dev

permissions:
contents: write
id-token: write

env:
PYTHON_VERSION: 3.12.6

jobs:
build-windows:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pyinstaller
pip install -r requirements.txt
- name: Build executable with PyInstaller
run: pyinstaller --onefile --noconsole --icon=./GUI-ver/icon.ico ./GUI-ver/flet-ui.py

- name: Zip executable and folders
run: |
mkdir release
cp -r ./dist/flet-ui.exe ./release/
cp -r ./core ./release/
cp -r ./GUI-ver/subs ./release/
powershell Compress-Archive -Path ./release/* -DestinationPath ./release/XC-windows.zip
- name: Upload Release Asset
uses: actions/upload-artifact@v3
with:
name: windows-release
path: ./release/XC-windows.zip

build-linux:
runs-on: ubuntu-latest
needs: build-windows
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pyinstaller
pip install -r requirements.txt
- name: Build executable with PyInstaller
run: pyinstaller --onefile --noconsole --icon=./GUI-ver/icon.ico ./GUI-ver/flet-ui.py

- name: Zip executable and folders
run: |
mkdir release
cp -r ./dist/flet-ui ./release/
cp -r ./core ./release/
cp -r ./GUI-ver/subs ./release/
zip -r ./release/XC-linux.zip ./release/
- name: Upload Release Asset
uses: actions/upload-artifact@v3
with:
name: linux-release
path: ./release/XC-linux.zip

build-macos:
runs-on: macos-latest
needs: build-windows
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pyinstaller
pip install pillow
pip install -r requirements.txt
- name: Build executable with PyInstaller
run: pyinstaller --onefile --noconsole --icon=./GUI-ver/icon.ico ./GUI-ver/flet-ui.py

- name: Zip executable and folders
run: |
mkdir release
cp -r ./dist/flet-ui ./release/
cp -r ./core ./release/
cp -r ./GUI-ver/subs ./release/
zip -r ./release/XC-macos.zip ./release/
- name: Upload Release Asset
uses: actions/upload-artifact@v3
with:
name: macos-release
path: ./release/XC-macos.zip

github-release:
name: Upload to GitHub Release
needs: [build-windows, build-linux, build-macos]
runs-on: ubuntu-latest

permissions:
contents: write
id-token: write

steps:
- name: Install GitHub CLI
run: sudo apt-get install gh

- name: Download Release Assets
uses: actions/download-artifact@v3
with:
name: windows-release
path: ./release/windows/

- name: Download Release Assets
uses: actions/download-artifact@v3
with:
name: linux-release
path: ./release/linux/

- name: Download Release Assets
uses: actions/download-artifact@v3
with:
name: macos-release
path: ./release/macos/

- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: >-
gh release create
"v4.1-${{ github.run_number }}"
--repo "${{ github.repository }}"
--notes ""
--prerelease
--generate-notes
--title "Release v4.1-${{ github.run_number }}"
- name: Upload artifacts to GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: >-
gh release upload
"v4.1-${{ github.run_number }}"
./release/windows/XC-windows.zip
--repo "${{ github.repository }}"
gh release upload
"v4.1-${{ github.run_number }}"
./release/linux/XC-linux.zip
--repo "${{ github.repository }}"
gh release upload
"v4.1-${{ github.run_number }}"
./release/macos/XC-macos.zip
--repo "${{ github.repository }}"
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ core/linux/select.txt
gui/test3.py
GUI-ver/test.py
subs/3ircle
GUI-ver/subs/3ircle
GUI-ver/subs/3ircle
core/win/select.txt
5 changes: 4 additions & 1 deletion GUI-ver/GUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def on_close():
import_page.config(bg="#0C0C0C")
import_page.title("import profile")
import_page.resizable(False, False)

if os_sys == "win" :
import_page.iconbitmap(str(ASSETS_PATH) + "/icon.ico")

name_label = Label(import_page,text="PROFILE NAME :",font=("calibri",15,"bold"),bg="#0C0C0C",fg="#ffffff")
name_label.place(x=12,y=12)
Expand Down Expand Up @@ -152,3 +153,5 @@ def on_close():
window.protocol("WM_DELETE_WINDOW", on_close)
import_page.protocol("WM_DELETE_WINDOW", func=lambda :on_close_import(import_page,import_btn,url_var,name_var))
window.mainloop()


180 changes: 180 additions & 0 deletions GUI-ver/backendflet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import os
import json
import base64
import requests
import subprocess
import platform
from pathlib import Path
import convert
import shutil
import time


class XrayBackend:
def __init__(self):
self.os_sys = self.os_det()
self.xray_process = None
self.version = "4.0"
self.xray_version = "1.8.24"

def os_det(self):
system_os = platform.system()
if system_os == "Windows":
return "win"
elif system_os == "Linux":
return "linux"
elif system_os == "Darwin":
return "macos"

def get_system_info(self):
return {
"OS": platform.system(),
"OS Version": platform.version(),
"Machine": platform.machine(),
"Processor": platform.processor()
}

def get_profiles(self):
profiles = []
path = "./subs"
if os.path.exists(path):
for sub in os.listdir(path):
if os.path.isdir(os.path.join(path, sub)):
profiles.append(sub)
return profiles

def get_configs(self, profile):
configs = []
path_json = f"./subs/{profile}/list.json"
if os.path.exists(path_json):
with open(path_json, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
for key, value in data.items():
configs.append(f"{key} - {value}")
return configs

def import_subscription(self, name, url):
headers = {"user-agent": "XC(Xray-Client)"}
r = requests.get(url=url, headers=headers)
text = r.text
decoded_bytes = base64.b64decode(text)
decoded_str = decoded_bytes.decode('utf-8')
list_configs = decoded_str.split("\n")

directory_path = f"./subs/{name}"
Path(directory_path).mkdir(parents=True, exist_ok=True)

dict_name = {}
for count, config in enumerate(list_configs):
if config.strip():
config_json, config_name = convert.convert(config)
if config_name != "False":
with open(f"./subs/{name}/{count}.json", "w") as f:
f.write(config_json)
dict_name[count] = config_name

with open(f"./subs/{name}/list.json", "w", encoding="utf-8") as f:
json.dump(dict_name, f, ensure_ascii=False, indent=4)
with open(f"./subs/{name}/url.txt", "w", encoding="utf-8") as f:
f.write(url)

def update_subscription(self, profile):
path = f"./subs/{profile}/url.txt"
with open(path, "r") as f:
url = f.read().strip()
self.import_subscription(profile, url)

def delete_subscription(self, profile):
directory_path = f"./subs/{profile}"
folder_path = Path(directory_path)
if folder_path.exists() and folder_path.is_dir():
for filename in os.listdir(directory_path):
file_path = os.path.join(directory_path, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
pass
# self.log(f"Error {file_path}: {e}")

shutil.rmtree(directory_path)

# self.log(f"Previous {profile} sub deleted")

def ping_config(self, profile, config_num, ping_type):
config_path = f"./subs/{profile}/{config_num}.json"

if ping_type == "Tcping":
try:
with open(config_path, 'r') as f:
config = json.load(f)
address = config['outbounds'][0]['settings']['vnext'][0]['address']
ping_cmd = ['ping', '-n', '1', '-w', '1000', address] if self.os_sys == "win" else ['ping', '-c', '1', '-W', '1', address]

if os.name == 'nt':
result = subprocess.Popen(ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, creationflags=subprocess.CREATE_NO_WINDOW)
else:
result = subprocess.Popen(ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout, stderr = result.communicate()
if result.returncode == 0:
time_p = stdout.split('time=')[1].split()[0]
return f"{time_p}"
else:
return "Timeout"

except Exception as e:
return f"Error: {str(e)}"

elif ping_type == "Real-delay":
if self.xray_process:
self.stop_xray()

self.run_xray(config_path)
time.sleep(2)
try:
s_time = time.time()
response = requests.get('http://gstatic.com/generate_204', proxies={"http": "http://127.0.0.1:1080"})
e_time = time.time()
if 200 <= response.status_code < 300:
delay_ms = (e_time - s_time) * 1000
return f"{delay_ms:.2f} ms"
else:
return "Timeout"
except :
self.stop_xray()
return f"Timeout"
finally:
self.stop_xray()


def run_xray(self, config_path):
try:
xray_path = f"./core/{self.os_sys}/xray"
creation_flags = subprocess.CREATE_NO_WINDOW if self.os_sys == "win" else 0
self.xray_process = subprocess.Popen(
[xray_path, '-config', config_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
creationflags=creation_flags
)
return f"Xray is running with config: {config_path}"
except Exception as e:
return f"Error starting Xray: {str(e)}"

def stop_xray(self):
if self.xray_process:
self.xray_process.terminate()
self.xray_process = None
return "Xray has been stopped."
return "Xray is not running."

def read_xray_logs(self):
while self.xray_process:
output = self.xray_process.stdout.readline()
if output == '' and self.xray_process.poll() is not None:
break
if output:
yield output.strip()
Loading

0 comments on commit 7b4ce7f

Please sign in to comment.