添加几个功能
This commit is contained in:
parent
a9bcd96046
commit
96518ebc5d
2 changed files with 166 additions and 14 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1 +1,3 @@
|
||||||
.venv
|
.venv
|
||||||
|
main/test.py
|
||||||
|
main/test1.py
|
176
main/main.py
176
main/main.py
|
@ -1,14 +1,25 @@
|
||||||
import sys
|
import sys
|
||||||
|
import platform
|
||||||
import requests
|
import requests
|
||||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu, QAction,QActionGroup
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu, QAction,QActionGroup
|
||||||
from PyQt5.QtGui import QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
|
from PyQt5.QtCore import QTimer,pyqtSignal,QThread
|
||||||
|
import json
|
||||||
|
import aiohttp
|
||||||
|
import asyncio
|
||||||
|
|
||||||
class TrayIconExample(QMainWindow):
|
class TrayIconExample(QMainWindow):
|
||||||
|
|
||||||
|
speed_data = pyqtSignal(dict)
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(TrayIconExample, self).__init__()
|
super(TrayIconExample, self).__init__()
|
||||||
|
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
|
# 启动异步任务
|
||||||
|
|
||||||
|
self.worker_thread = WorkerThread(self)
|
||||||
|
self.worker_thread.data_ready.connect(self.update_speed_data)
|
||||||
|
self.worker_thread.start()
|
||||||
|
|
||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
self.setWindowTitle('Clash Tray')
|
self.setWindowTitle('Clash Tray')
|
||||||
|
@ -23,11 +34,39 @@ class TrayIconExample(QMainWindow):
|
||||||
exit_action = QAction('退出', self)
|
exit_action = QAction('退出', self)
|
||||||
self.tun_mode = QAction('TUN模式', self)
|
self.tun_mode = QAction('TUN模式', self)
|
||||||
self.tun_mode.setCheckable(True)
|
self.tun_mode.setCheckable(True)
|
||||||
|
# 获取环境变量
|
||||||
|
self.copy_env=QAction('复制环境变量',self)
|
||||||
|
|
||||||
# 创建一个 QActionGroup
|
self.more_menu=QMenu('更多',self)
|
||||||
|
self.upload_speed=QAction('⬆️上传速度',self)
|
||||||
|
self.download_speed=QAction('⬇️下载速度',self)
|
||||||
|
self.upload_speed.setCheckable(False)
|
||||||
|
self.upload_speed.setEnabled(False)
|
||||||
|
self.download_speed.setCheckable(False)
|
||||||
|
self.download_speed.setEnabled(False)
|
||||||
|
|
||||||
|
# self.timer = QTimer(self)
|
||||||
|
# self.timer.timeout.connect(self.update_data)
|
||||||
|
# self.timer.start(1000) # 定时器间隔为1000毫秒(1秒)
|
||||||
|
|
||||||
|
# 更多 子菜单项设置
|
||||||
|
self.version=self.get_version()
|
||||||
|
self.show_version = QAction('内核版本:'+self.version, self)
|
||||||
|
self.show_version.setCheckable(False)
|
||||||
|
self.show_version.setEnabled(False)
|
||||||
|
self.restart_core=QAction('重启Clash',self)
|
||||||
|
|
||||||
|
self.more_menu.addAction(self.restart_core)
|
||||||
|
self.more_menu.addAction(self.show_version)
|
||||||
|
|
||||||
|
|
||||||
|
self.restart_core.triggered.connect(self.restart_clash)
|
||||||
|
|
||||||
|
|
||||||
|
# 创建代理模式 QActionGroup
|
||||||
proxy_mode_group = QActionGroup(self)
|
proxy_mode_group = QActionGroup(self)
|
||||||
proxy_mode_group.setExclusive(True) # 设置为单选模式
|
proxy_mode_group.setExclusive(True) # 设置为单选模式
|
||||||
|
# 设置代理模式菜单
|
||||||
self.direct_mode=QAction('直连模式',self)
|
self.direct_mode=QAction('直连模式',self)
|
||||||
self.rule_mode=QAction('规则模式',self)
|
self.rule_mode=QAction('规则模式',self)
|
||||||
self.global_mode=QAction('全局模式',self)
|
self.global_mode=QAction('全局模式',self)
|
||||||
|
@ -39,12 +78,20 @@ class TrayIconExample(QMainWindow):
|
||||||
proxy_mode_group.addAction(self.rule_mode)
|
proxy_mode_group.addAction(self.rule_mode)
|
||||||
proxy_mode_group.addAction(self.global_mode)
|
proxy_mode_group.addAction(self.global_mode)
|
||||||
|
|
||||||
|
self.tun_mode.triggered.connect(self.change_tun_mode)
|
||||||
exit_action.triggered.connect(self.exit_application)
|
exit_action.triggered.connect(self.exit_application)
|
||||||
|
# 将菜单添加到托盘图标
|
||||||
context_menu.addAction(self.tun_mode)
|
context_menu.addAction(self.tun_mode)
|
||||||
context_menu.addMenu(proxy_mode)
|
context_menu.addMenu(proxy_mode)
|
||||||
|
context_menu.addAction(self.copy_env)
|
||||||
context_menu.addAction(exit_action)
|
context_menu.addMenu(self.more_menu)
|
||||||
|
context_menu.addActions([self.upload_speed,self.download_speed,exit_action])
|
||||||
proxy_mode.addActions([self.direct_mode,self.rule_mode,self.global_mode])
|
proxy_mode.addActions([self.direct_mode,self.rule_mode,self.global_mode])
|
||||||
|
|
||||||
|
self.copy_env.triggered.connect(self.copy_env_var)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.direct_mode.triggered.connect(lambda:self.set_proxy_mode(0))
|
self.direct_mode.triggered.connect(lambda:self.set_proxy_mode(0))
|
||||||
self.rule_mode.triggered.connect(lambda:self.set_proxy_mode(1))
|
self.rule_mode.triggered.connect(lambda:self.set_proxy_mode(1))
|
||||||
self.global_mode.triggered.connect(lambda:self.set_proxy_mode(2))
|
self.global_mode.triggered.connect(lambda:self.set_proxy_mode(2))
|
||||||
|
@ -57,7 +104,14 @@ class TrayIconExample(QMainWindow):
|
||||||
tray_icon.show()
|
tray_icon.show()
|
||||||
self.get_config()
|
self.get_config()
|
||||||
|
|
||||||
self.setGeometry(100, 100, 800, 600)
|
self.setGeometry(200, 200, 1200, 800)
|
||||||
|
|
||||||
|
def restart_clash(self):
|
||||||
|
url,port=self.get_connect()
|
||||||
|
data={'path': '','payload': ''}
|
||||||
|
response=requests.post(url=url+':'+port+'/restart').json()
|
||||||
|
if response['status']=='ok':
|
||||||
|
print('重启成功')
|
||||||
|
|
||||||
def get_connect(self,url=None,port=None):
|
def get_connect(self,url=None,port=None):
|
||||||
url='http://127.0.0.1'
|
url='http://127.0.0.1'
|
||||||
|
@ -83,34 +137,130 @@ class TrayIconExample(QMainWindow):
|
||||||
self.tun_mode.setChecked(True)
|
self.tun_mode.setChecked(True)
|
||||||
else:
|
else:
|
||||||
self.tun_mode.setChecked(False)
|
self.tun_mode.setChecked(False)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def get_version(self):
|
||||||
|
url,port=self.get_connect()
|
||||||
|
response=requests.get(url=url+':'+port+'/version')
|
||||||
|
if response.status_code==200:
|
||||||
|
res=response.json()
|
||||||
|
print('version',res)
|
||||||
|
return res['version']
|
||||||
def set_proxy_mode(self,type):
|
def set_proxy_mode(self,type):
|
||||||
mode=None
|
mode=None
|
||||||
if type==0:
|
if type==0:
|
||||||
mode='direct'
|
mode='direct'
|
||||||
# self.rule_mode.setChecked(True)
|
|
||||||
elif type==1:
|
elif type==1:
|
||||||
mode='rule'
|
mode='rule'
|
||||||
# self.rule_mode.setChecked(True)
|
|
||||||
elif type==2:
|
elif type==2:
|
||||||
mode='global'
|
mode='global'
|
||||||
# self.global_mode.setChecked(True)
|
|
||||||
url,port=self.get_connect()
|
url,port=self.get_connect()
|
||||||
data = {"mode": mode}
|
data = {"mode": mode}
|
||||||
response=requests.patch(url=url+':'+port+'/configs?force=true',json=data)
|
response=requests.patch(url=url+':'+port+'/configs?force=true',json=data)
|
||||||
if response.status_code==204:
|
if response.status_code==204:
|
||||||
self.get_config()
|
self.get_config()
|
||||||
|
def change_tun_mode(self):
|
||||||
|
url,port=self.get_connect()
|
||||||
|
print(self.tun_mode.isChecked())
|
||||||
|
data = {"tun": {"enable": False if self.tun_mode.isChecked() else True}}
|
||||||
|
print(data)
|
||||||
|
response=requests.patch(url=url+':'+port+'/configs?force=true',json=data)
|
||||||
|
if response.status_code==204:
|
||||||
|
self.get_config()
|
||||||
|
|
||||||
|
def copy_env_var(self):
|
||||||
|
sys_info=platform.uname()
|
||||||
|
clipboard = QApplication.clipboard()
|
||||||
|
env_var=''
|
||||||
|
# print(sys_info.system)
|
||||||
|
if sys_info.system == ('Linux' or 'Darwin'):
|
||||||
|
env_var='export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890'
|
||||||
|
elif sys_info.system == 'Windows':
|
||||||
|
env_var='setx https_proxy=http://127.0.0.1:7890\nsetx http_proxy=http://127.0.0.1:7890\nsetx all_proxy=socks5://127.0.0.1:7890'
|
||||||
|
|
||||||
|
# print(env_var)
|
||||||
|
clipboard.setText(env_var)
|
||||||
|
|
||||||
|
def update_speed_data(self,data):
|
||||||
|
print(data)
|
||||||
|
upload=data['up']
|
||||||
|
down=data['down']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if upload /1024<=1024 or down /1024<=1024:
|
||||||
|
upload=round(upload/1024,2)
|
||||||
|
down=round(down/1024,2)
|
||||||
|
self.upload_speed.setText('上传速度:'+str(upload)+'KB/s')
|
||||||
|
self.download_speed.setText('下载速度:'+str(down)+'KB/s')
|
||||||
|
else:
|
||||||
|
upload=round(upload/1024/1024,2)
|
||||||
|
down=round(down/1024/1024,2)
|
||||||
|
self.upload_speed.setText('上传速度:'+str(upload)+'MB/s')
|
||||||
|
self.download_speed.setText('下载速度:'+str(down)+'MB/s')
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
def exit_application(self):
|
def exit_application(self):
|
||||||
QApplication.quit()
|
QApplication.quit()
|
||||||
|
|
||||||
|
|
||||||
|
# async def fetch_and_output_data(self):
|
||||||
|
# url = "http://127.0.0.1:9090/traffic" # 替换为实际的 API 地址
|
||||||
|
# async with aiohttp.ClientSession() as session:
|
||||||
|
# async with session.get(url, timeout=None) as response: # timeout=None 表示不设置超时
|
||||||
|
# while True:
|
||||||
|
# partial_data = await response.content.read(100) # 每次读取100字节的数据示例
|
||||||
|
|
||||||
|
# if not partial_data:
|
||||||
|
# break # 如果没有更多数据,退出循环
|
||||||
|
|
||||||
|
# # 在此处可以进行异步加载部分数据的操作,例如使用 Qt 的异步加载机制
|
||||||
|
# # print("Partial data:", partial_data)
|
||||||
|
|
||||||
|
# # 将字节数据转换为字符串
|
||||||
|
# partial_data_str = partial_data.decode('utf-8')
|
||||||
|
|
||||||
|
# print(partial_data_str)
|
||||||
|
|
||||||
|
# # 将字符串解析为 JSON 对象
|
||||||
|
# try:
|
||||||
|
# partial_data_json = json.loads(partial_data_str)
|
||||||
|
# print("Partial data:", partial_data_json)
|
||||||
|
# self.speed_data.emit(partial_data_json)
|
||||||
|
# except json.JSONDecodeError as e:
|
||||||
|
# print(f"Error decoding JSON: {e}")
|
||||||
|
|
||||||
|
# await asyncio.sleep(1) # 休眠1秒,模拟每秒输出一部分数据
|
||||||
|
|
||||||
|
class WorkerThread(QThread):
|
||||||
|
data_ready = pyqtSignal(dict)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
asyncio.set_event_loop(loop)
|
||||||
|
loop.run_until_complete(self.fetch_and_output_data())
|
||||||
|
|
||||||
|
async def fetch_and_output_data(self):
|
||||||
|
url = "http://127.0.0.1:9090/traffic"
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(url, timeout=None) as response:
|
||||||
|
while True:
|
||||||
|
partial_data = await response.content.read(100)
|
||||||
|
|
||||||
|
if not partial_data:
|
||||||
|
break
|
||||||
|
|
||||||
|
partial_data_str = partial_data.decode('utf-8')
|
||||||
|
|
||||||
|
try:
|
||||||
|
partial_data_json = json.loads(partial_data_str)
|
||||||
|
self.data_ready.emit(partial_data_json)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
print(f"解析 JSON 时出错:{e}")
|
||||||
|
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
window = TrayIconExample()
|
window = TrayIconExample()
|
||||||
|
|
Loading…
Reference in a new issue