Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
jiangxufeng authored Nov 15, 2019
2 parents 063a336 + 15f5bf4 commit 4b6143a
Show file tree
Hide file tree
Showing 8 changed files with 1,264 additions and 284 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ v2ray linux 客户端,使用pyqt5编写GUI界面,核心基于v2ray-core(v2ra
- 设置自动更新订阅、更换地址
- 支持协议:vmess、shadowsocks
- 通过`vmess://``ss://`分享链接添加配置,通过二维码添加配置
- 手动添加配置,修改本地监听端口
- 导出配置、生成配置分享链接、生成分享二维码
- 最小化至托盘、测试延时、检查更新
- ......
Expand Down Expand Up @@ -60,9 +61,9 @@ bash <(curl -s -L http://dl.thinker.ink/uninstall.sh)

![首页](http://cloud.thinker.ink/download/a043a08860f239f8d0cbeb2dc2a5b6d5.png)

![setting1](http://cloud.thinker.ink/download/c32e16f3b205b25c615b86a7beb8eb8d.png)
![setting1](http://cloud.thinker.ink/images/364231980b07e8881164f61cd220d0bb.png)

![setting2](http://cloud.thinker.ink/images/cc18605727deaf878cb0a2fa07ec230f.png)
![setting2](http://cloud.thinker.ink/images/8835526765d479143879c08fe1ecb8a4.png)

# 感谢

Expand Down
5 changes: 4 additions & 1 deletion v2rayL-GUI/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
}
],
"log": {
"loglevel": "warning"
"loglevel": "warning",
"access": "/etc/v2rayL/v2ray_access.log",
"error": "/etc/v2rayL/v2ray_error.log",

},
"outbounds": [{
"mux": {
Expand Down
575 changes: 501 additions & 74 deletions v2rayL-GUI/new_ui.py

Large diffs are not rendered by default.

126 changes: 107 additions & 19 deletions v2rayL-GUI/sub2conf_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import json
import pickle
import requests
import ast
import copy
import urllib.parse as parse
from config import conf_template as conf
from config import conf_template as tpl


class Sub2Conf(object):
Expand Down Expand Up @@ -40,8 +42,15 @@ def __init__(self, subs_url=None, conf_url=None):
'''

def b642conf(self, prot, tp, b64str):
"""
base64转化为dict类型配置
:param prot:
:param tp:
:param b64str:
:return:
"""
if prot == "vmess":
ret = json.loads(parse.unquote(base64.b64decode(b64str).decode()))
ret = json.loads(parse.unquote(base64.b64decode(b64str).decode()).replace("\'", "\""))
region = ret['ps']

elif prot == "shadowsocks":
Expand All @@ -65,8 +74,19 @@ def b642conf(self, prot, tp, b64str):
region = region + "_local"
self.saved_conf[["local", "subs"][tp]][region] = ret

def setconf(self, region):
def setconf(self, region, http, socks):
"""
生成配置
:param region: 当前VPN别名
:param http: http端口
:param socks: socks端口
:return:
"""
use_conf = self.conf[region]
conf = copy.deepcopy(tpl)
conf["inbounds"][0]["port"] = socks
conf["inbounds"][1]["port"] = http

if use_conf['prot'] == "vmess":
conf['outbounds'][0]["protocol"] = "vmess"
conf['outbounds'][0]["settings"]["vnext"] = list()
Expand All @@ -89,7 +109,7 @@ def setconf(self, region):
"security": "tls" if use_conf["tls"] else "",
"tlssettings": {
"allowInsecure": True,
"serverName": use_conf["tls"]
"serverName": use_conf["host"] if use_conf["tls"] else ""
},
"wssettings": {
"connectionReuse": True,
Expand All @@ -115,8 +135,48 @@ def setconf(self, region):
"uplinkCapacity": 12,
"writeBufferSize": 1
},
"security": ""
"security": "tls" if use_conf["tls"] else ""
}
# tcp
elif use_conf["net"] == "tcp":
conf['outbounds'][0]["streamSettings"] = {
"network": use_conf["net"],
"security": "tls" if use_conf["tls"] else "",
"tcpsettings": {
"connectionReuse": True,
"header": {
"request": {
"version": "1.1",
"method": "GET",
"path": [use_conf["path"]],
"headers": {
"User-Agent": ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"],
"Accept-Encoding": ["gzip, deflate"],
"Connection": ["keep-alive"],
"Pragma": "no-cache",
"Host": [use_conf["host"]]
}
},
"type": use_conf["type"]
}
} if use_conf["type"] != "none" else {}
}
# QUIC
# elif use_conf["net"] == "quic":
# conf['outbounds'][0]["streamSettings"] = {
# "network": use_conf["net"],
# "security": "tls" if use_conf["tls"] else "none",
# "tlssettings": {
# "allowInsecure": True,
# "serverName": use_conf["host"]
# },
# "quicsettings": {
# "headers": {
# "type": use_conf['type']
# },
# "key":
# }
# }

elif use_conf['prot'] == "shadowsocks":
conf['outbounds'][0]["protocol"] = "shadowsocks"
Expand All @@ -136,6 +196,11 @@ def setconf(self, region):
f.write(json.dumps(conf, indent=4))

def delconf(self, region):
"""
删除一个配置
:param region: 配置名
:return:
"""
self.conf.pop(region)
try:
self.saved_conf['local'].pop(region)
Expand All @@ -147,25 +212,47 @@ def delconf(self, region):
with open("/etc/v2rayL/ndata", "wb") as jf:
pickle.dump(self.saved_conf, jf)

def update(self):
def update(self, flag):
"""
更新订阅
:param flag: True, 整体更新, False, 添加
"""
try:
ret = requests.get(self.subs_url)
if ret.status_code != 200:
raise MyException("无法获取订阅信息,订阅站点访问失败")
all_subs = base64.b64decode(ret.text + "==").decode().strip()
if "vmess" not in all_subs or "ss" not in all_subs:
raise MyException("解析订阅信息失败,请确认链接正确")
all_subs = all_subs.split("\n")
except:
raise MyException("解析订阅信息失败")
error_subs = []
if flag:
all_subs = []
for url in self.subs_url:
# print(url)
try:
ret = requests.get(url[1], timeout=15)
if ret.status_code != 200:
error_subs.append([url, "无法获取订阅信息,订阅站点访问失败"])
raise MyException("无法获取订阅信息,订阅站点访问失败")
subs = base64.b64decode(ret.text + "==").decode().strip()
all_subs.extend(subs.split("\n"))
except:
pass
# raise MyException(e.args[0])
# error_subs.append(url)

for sub in all_subs:
self.origin.append(sub.split("://"))

for sub in all_subs:
self.origin.append(sub.split("://"))
self.saved_conf["subs"] = {}

else:
try:
ret = requests.get(self.subs_url, timeout=15)
if ret.status_code != 200:
raise MyException("无法获取订阅信息,订阅站点访问失败")
all_subs = base64.b64decode(ret.text + "==").decode().strip()
if "vmess" not in all_subs or "ss" not in all_subs:
raise MyException("解析订阅信息失败,请确认链接正确")
all_subs = all_subs.split("\n")
except Exception as e:
raise MyException(e.args[0])

self.saved_conf["subs"] = {}
for sub in all_subs:
self.origin.append(sub.split("://"))

for ori in self.origin:
if ori[0] == "vmess":
Expand All @@ -178,6 +265,7 @@ def update(self):
with open("/etc/v2rayL/ndata", "wb") as jf:
pickle.dump(self.saved_conf, jf)

return error_subs
def add_conf_by_uri(self):
"""
通过分享的连接添加配置
Expand Down
79 changes: 79 additions & 0 deletions v2rayL-GUI/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# -*- coding:utf-8 -*-
# Author: Suummmmer
# Date: 2019-10-24

import sys
import datetime
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox, qApp
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import (
QtInfoMsg,
QtWarningMsg,
QtCriticalMsg,
QtFatalMsg
)


class SystemTray(object):
# 程序托盘类
def __init__(self, w, app):
self.app = app
self.w = w
QApplication.setQuitOnLastWindowClosed(False) # 禁止默认的closed方法,
self.w.show() # 不设置显示则为启动最小化到托盘
self.tp = QSystemTrayIcon(self.w)
self.initUI()
self.run()

# sys.stdout = EmittingStream(textWritten=self.w.output_ter_result)
# sys.stderr = EmittingStream(textWritten=self.w.output_ter_result)

def initUI(self):
# 设置托盘图标
self.tp.setIcon(QIcon('/etc/v2rayL/images/logo.ico'))

def quitApp(self):
# 退出程序
self.w.show() # w.hide() #设置退出时是否显示主窗口
re = QMessageBox.question(self.w, "提示", "确认退出?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if re == QMessageBox.Yes:
self.tp.setVisible(False) # 隐藏托盘控件
qApp.quit() # 退出程序
self.w.v2rayL.disconnect()

def act(self, reason):
# 主界面显示方法
if reason == 2 or reason == 3:
self.w.show()

def run(self):
self.w.a2.triggered.connect(self.quitApp)
self.tp.setContextMenu(self.w.tpMenu)
self.tp.show() # 不调用show不会显示系统托盘消息,图标隐藏无法调用

# 绑定提醒信息点击事件
# self.tp.messageClicked.connect(self.message)
# 绑定托盘菜单点击事件
self.tp.activated.connect(self.act)
sys.exit(self.app.exec_()) # 持续对app的连接


def qt_message_handler(mode, context, message):
if mode == QtInfoMsg:
mode = 'INFO'
elif mode == QtWarningMsg:
mode = 'WARNING'
elif mode == QtCriticalMsg:
mode = 'CRITICAL'
elif mode == QtFatalMsg:
mode = 'FATAL'
else:
mode = 'DEBUG'

en, info = message.split("@$ff$@")
if en == "True":
with open("/etc/v2rayL/v2rayL_op.log", "a+") as f:
f.write(' %s - %s: %s\n' % (datetime.datetime.now(), mode, info))

# https://sub.qianglie.xyz/subscribe.php?sid=5582&token=g6e8VdU6C40H
Loading

0 comments on commit 4b6143a

Please sign in to comment.