mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-19 22:50:08 +08:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adef6cd4af | ||
|
|
399b171adf | ||
|
|
6e4c180428 | ||
|
|
75c6496151 | ||
|
|
62c59f6fd3 | ||
|
|
12d6fc24e7 | ||
|
|
6de7c588b6 | ||
|
|
99c8d50943 | ||
|
|
2a177256ce | ||
|
|
b1d1674912 | ||
|
|
2dd9cf45eb | ||
|
|
96a6586c5e | ||
|
|
375ffec58d | ||
|
|
7aa863b881 | ||
|
|
79838d8679 |
18
.github/workflows/update-pkgbuild.yml
vendored
Normal file
18
.github/workflows/update-pkgbuild.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: AUR CI
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- 'LICENSE'
|
||||||
|
- '!.github/workflows/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: chitang233/aur-pkgbuild-builder@main
|
||||||
|
with:
|
||||||
|
deploy_key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
package_name: 'nekoray-git'
|
||||||
@ -353,7 +353,7 @@ namespace Qv2ray::components::proxy {
|
|||||||
// execute and get the code
|
// execute and get the code
|
||||||
const auto returnCode = QProcess::execute(action.first, action.second);
|
const auto returnCode = QProcess::execute(action.first, action.second);
|
||||||
// print out the commands and result codes
|
// print out the commands and result codes
|
||||||
DEBUG(QString("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
|
DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
|
||||||
// give the code back
|
// give the code back
|
||||||
results << (returnCode == QProcess::NormalExit);
|
results << (returnCode == QProcess::NormalExit);
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ namespace Qv2ray::components::proxy {
|
|||||||
// execute and get the code
|
// execute and get the code
|
||||||
const auto returnCode = QProcess::execute(action.first, action.second);
|
const auto returnCode = QProcess::execute(action.first, action.second);
|
||||||
// print out the commands and result codes
|
// print out the commands and result codes
|
||||||
DEBUG(QString("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
|
DEBUG(QStringLiteral("[%1] Program: %2, Args: %3").arg(returnCode).arg(action.first).arg(action.second.join(";")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
132
3rdparty/qv2ray/v2/ui/LogHighlighter.cpp
vendored
132
3rdparty/qv2ray/v2/ui/LogHighlighter.cpp
vendored
@ -1,132 +0,0 @@
|
|||||||
#include "LogHighlighter.hpp"
|
|
||||||
|
|
||||||
#define TO_EOL "(([\\s\\S]*)|([\\d\\D]*)|([\\w\\W]*))$"
|
|
||||||
#define REGEX_IPV6_ADDR \
|
|
||||||
R"(\[\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*\])"
|
|
||||||
#define REGEX_IPV4_ADDR \
|
|
||||||
R"((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))"
|
|
||||||
#define REGEX_PORT_NUMBER R"(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])*)"
|
|
||||||
|
|
||||||
namespace Qv2ray::ui {
|
|
||||||
SyntaxHighlighter::SyntaxHighlighter(bool darkMode, QTextDocument *parent) : QSyntaxHighlighter(parent) {
|
|
||||||
HighlightingRule rule;
|
|
||||||
|
|
||||||
if (darkMode) {
|
|
||||||
tcpudpFormat.setForeground(QColor(0, 200, 230));
|
|
||||||
ipHostFormat.setForeground(Qt::yellow);
|
|
||||||
warningFormat.setForeground(QColor(255, 160, 15));
|
|
||||||
warningFormat2.setForeground(Qt::cyan);
|
|
||||||
} else {
|
|
||||||
ipHostFormat.setForeground(QColor(0, 52, 130));
|
|
||||||
tcpudpFormat.setForeground(QColor(0, 52, 130));
|
|
||||||
warningFormat.setBackground(QColor(255, 160, 15));
|
|
||||||
warningFormat.setForeground(Qt::white);
|
|
||||||
warningFormat2.setForeground(Qt::darkCyan);
|
|
||||||
}
|
|
||||||
const static QColor darkGreenColor(10, 180, 0);
|
|
||||||
|
|
||||||
acceptedFormat.setForeground(darkGreenColor);
|
|
||||||
acceptedFormat.setFontItalic(true);
|
|
||||||
acceptedFormat.setFontWeight(QFont::Bold);
|
|
||||||
rule.pattern = QRegularExpression("\\saccepted\\s");
|
|
||||||
rule.format = acceptedFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
rejectedFormat.setFontWeight(QFont::Bold);
|
|
||||||
rejectedFormat.setBackground(Qt::red);
|
|
||||||
rejectedFormat.setForeground(Qt::white);
|
|
||||||
rejectedFormat.setFontWeight(QFont::Bold);
|
|
||||||
rule.pattern = QRegularExpression("\\srejected\\s" TO_EOL);
|
|
||||||
rule.format = rejectedFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
dateFormat.setForeground(darkMode ? Qt::cyan : Qt::darkCyan);
|
|
||||||
rule.pattern = QRegularExpression("\\d\\d\\d\\d/\\d\\d/\\d\\d");
|
|
||||||
rule.format = dateFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
timeFormat.setForeground(darkMode ? Qt::cyan : Qt::darkCyan);
|
|
||||||
rule.pattern = QRegularExpression("\\d\\d:\\d\\d:\\d\\d");
|
|
||||||
rule.format = timeFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
debugFormat.setForeground(Qt::darkGray);
|
|
||||||
rule.pattern = QRegularExpression("\\[D[Ee][Bb][Uu].*?\\]");
|
|
||||||
rule.format = debugFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
infoFormat.setForeground(darkMode ? Qt::lightGray : Qt::darkCyan);
|
|
||||||
rule.pattern = QRegularExpression("\\[I[Nn][Ff][Oo].*?\\]");
|
|
||||||
rule.format = infoFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
warningFormat.setFontWeight(QFont::Bold);
|
|
||||||
warningFormat2.setFontWeight(QFont::Bold);
|
|
||||||
rule.pattern = QRegularExpression("\\[W[Aa][Rr][Nn].*?\\]");
|
|
||||||
rule.format = warningFormat2;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
rule.pattern = QRegularExpression("\\[E[Rr][Rr][Oo].*?\\]");
|
|
||||||
rule.format = rejectedFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
|
|
||||||
//
|
|
||||||
v2rayComponentFormat.setForeground(darkMode ? darkGreenColor : Qt::darkYellow);
|
|
||||||
rule.pattern = QRegularExpression(R"( (\w+\/)+\w+: )");
|
|
||||||
rule.format = v2rayComponentFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
failedFormat.setFontWeight(QFont::Bold);
|
|
||||||
failedFormat.setBackground(Qt::red);
|
|
||||||
failedFormat.setForeground(Qt::white);
|
|
||||||
rule.pattern = QRegularExpression("failed");
|
|
||||||
rule.format = failedFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
rule.pattern = QRegularExpression(">>>>+");
|
|
||||||
rule.format = warningFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
rule.pattern = QRegularExpression("<<<<+");
|
|
||||||
rule.format = warningFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
|
|
||||||
{
|
|
||||||
// IP IPv6 Host;
|
|
||||||
rule.pattern = QRegularExpression(REGEX_IPV4_ADDR ":" REGEX_PORT_NUMBER);
|
|
||||||
rule.pattern.setPatternOptions(QRegularExpression::ExtendedPatternSyntaxOption);
|
|
||||||
rule.format = ipHostFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
rule.pattern = QRegularExpression(REGEX_IPV6_ADDR ":" REGEX_PORT_NUMBER);
|
|
||||||
rule.pattern.setPatternOptions(QRegularExpression::ExtendedPatternSyntaxOption);
|
|
||||||
rule.format = ipHostFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
//
|
|
||||||
rule.pattern = QRegularExpression("([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/|):" REGEX_PORT_NUMBER);
|
|
||||||
rule.pattern.setPatternOptions(QRegularExpression::PatternOption::ExtendedPatternSyntaxOption);
|
|
||||||
rule.format = ipHostFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &pattern: {"tcp:", "udp:"}) {
|
|
||||||
tcpudpFormat.setFontWeight(QFont::Bold);
|
|
||||||
rule.pattern = QRegularExpression(pattern);
|
|
||||||
rule.format = tcpudpFormat;
|
|
||||||
highlightingRules.append(rule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SyntaxHighlighter::highlightBlock(const QString &text) {
|
|
||||||
for (const HighlightingRule &rule: highlightingRules) {
|
|
||||||
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
|
|
||||||
|
|
||||||
while (matchIterator.hasNext()) {
|
|
||||||
QRegularExpressionMatch match = matchIterator.next();
|
|
||||||
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentBlockState(0);
|
|
||||||
}
|
|
||||||
} // namespace Qv2ray::ui
|
|
||||||
92
3rdparty/qv2ray/v2/ui/LogHighlighter.hpp
vendored
92
3rdparty/qv2ray/v2/ui/LogHighlighter.hpp
vendored
@ -1,92 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of the examples of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:BSD$
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** BSD License Usage
|
|
||||||
** Alternatively, you may use this file under the terms of the BSD license
|
|
||||||
** as follows:
|
|
||||||
**
|
|
||||||
** "Redistribution and use in source and binary forms, with or without
|
|
||||||
** modification, are permitted provided that the following conditions are
|
|
||||||
** met:
|
|
||||||
** * Redistributions of source code must retain the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer.
|
|
||||||
** * Redistributions in binary form must reproduce the above copyright
|
|
||||||
** notice, this list of conditions and the following disclaimer in
|
|
||||||
** the documentation and/or other materials provided with the
|
|
||||||
** distribution.
|
|
||||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
|
||||||
** contributors may be used to endorse or promote products derived
|
|
||||||
** from this software without specific prior written permission.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QSyntaxHighlighter>
|
|
||||||
#include <QTextCharFormat>
|
|
||||||
#include <QTextDocument>
|
|
||||||
|
|
||||||
namespace Qv2ray {
|
|
||||||
namespace ui {
|
|
||||||
class SyntaxHighlighter : public QSyntaxHighlighter {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SyntaxHighlighter(bool darkMode, QTextDocument *parent = nullptr);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void highlightBlock(const QString &text) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct HighlightingRule {
|
|
||||||
QRegularExpression pattern;
|
|
||||||
QTextCharFormat format;
|
|
||||||
};
|
|
||||||
QVector<HighlightingRule> highlightingRules;
|
|
||||||
|
|
||||||
QTextCharFormat tcpudpFormat;
|
|
||||||
QTextCharFormat dateFormat;
|
|
||||||
QTextCharFormat acceptedFormat;
|
|
||||||
QTextCharFormat rejectedFormat;
|
|
||||||
QTextCharFormat failedFormat;
|
|
||||||
QTextCharFormat warningFormat;
|
|
||||||
QTextCharFormat warningFormat2;
|
|
||||||
QTextCharFormat infoFormat;
|
|
||||||
QTextCharFormat debugFormat;
|
|
||||||
QTextCharFormat timeFormat;
|
|
||||||
QTextCharFormat ipHostFormat;
|
|
||||||
QTextCharFormat v2rayComponentFormat;
|
|
||||||
};
|
|
||||||
} // namespace ui
|
|
||||||
} // namespace Qv2ray
|
|
||||||
|
|
||||||
using namespace Qv2ray::ui;
|
|
||||||
@ -191,13 +191,13 @@ QVariant QJsonModel::data(const QModelIndex &index, int role) const {
|
|||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
if (index.column() == 0)
|
if (index.column() == 0)
|
||||||
return QString("%1").arg(item->key());
|
return QStringLiteral("%1").arg(item->key());
|
||||||
|
|
||||||
if (index.column() == 1)
|
if (index.column() == 1)
|
||||||
return QString("%1").arg(item->value());
|
return QStringLiteral("%1").arg(item->value());
|
||||||
} else if (Qt::EditRole == role) {
|
} else if (Qt::EditRole == role) {
|
||||||
if (index.column() == 1) {
|
if (index.column() == 1) {
|
||||||
return QString("%1").arg(item->value());
|
return QStringLiteral("%1").arg(item->value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -131,7 +131,6 @@ set(PROJECT_SOURCES
|
|||||||
3rdparty/qrcodegen.cpp
|
3rdparty/qrcodegen.cpp
|
||||||
3rdparty/QtExtKeySequenceEdit.cpp
|
3rdparty/QtExtKeySequenceEdit.cpp
|
||||||
|
|
||||||
3rdparty/qv2ray/v2/ui/LogHighlighter.cpp
|
|
||||||
3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp
|
3rdparty/qv2ray/v2/ui/QvAutoCompleteTextEdit.cpp
|
||||||
3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp
|
3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.cpp
|
||||||
3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp
|
3rdparty/qv2ray/v2/ui/widgets/common/QJsonModel.cpp
|
||||||
|
|||||||
10
README.md
10
README.md
@ -8,16 +8,6 @@ Support Windows / Linux out of the box now.
|
|||||||
|
|
||||||
目前支持 Windows / Linux 开箱即用
|
目前支持 Windows / Linux 开箱即用
|
||||||
|
|
||||||
## 4.x 开发计划
|
|
||||||
|
|
||||||
软件定位:电脑端节点调试软件。更新频率随机,可用性无保证。机场订阅用户建议使用 Clash Verge Rev 等。
|
|
||||||
|
|
||||||
1. 移除 Xray 核心,更新 sing-box。
|
|
||||||
2. 移除一些没用的功能。
|
|
||||||
3. 更新文档。
|
|
||||||
4. 更新部分依赖
|
|
||||||
5. 移除 macos 遗留
|
|
||||||
|
|
||||||
## 下载 / Download
|
## 下载 / Download
|
||||||
|
|
||||||
### GitHub Releases (Portable ZIP)
|
### GitHub Releases (Portable ZIP)
|
||||||
|
|||||||
@ -22,30 +22,48 @@ namespace NekoGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString genTunName() {
|
QString genTunName() {
|
||||||
auto tun_name = "nekobox-tun";
|
auto tun_name = "neko-tun";
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
tun_name = "utun9";
|
tun_name = "utun9";
|
||||||
#endif
|
#endif
|
||||||
return tun_name;
|
return tun_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergeJson(const QJsonObject &custom, QJsonObject &outbound) {
|
void MergeJson(QJsonObject &dst, const QJsonObject &src) {
|
||||||
// 合并
|
// 合并
|
||||||
if (custom.isEmpty()) return;
|
if (src.isEmpty()) return;
|
||||||
for (const auto &key: custom.keys()) {
|
for (const auto &key: src.keys()) {
|
||||||
if (outbound.contains(key)) {
|
auto v_src = src[key];
|
||||||
auto v = custom[key];
|
if (dst.contains(key)) {
|
||||||
auto v_orig = outbound[key];
|
auto v_dst = dst[key];
|
||||||
if (v.isObject() && v_orig.isObject()) { // isObject 则合并?
|
if (v_src.isObject() && v_dst.isObject()) { // isObject 则合并?
|
||||||
auto vo = v.toObject();
|
auto v_src_obj = v_src.toObject();
|
||||||
QJsonObject vo_orig = v_orig.toObject();
|
auto v_dst_obj = v_dst.toObject();
|
||||||
MergeJson(vo, vo_orig);
|
MergeJson(v_dst_obj, v_src_obj);
|
||||||
outbound[key] = vo_orig;
|
dst[key] = v_dst_obj;
|
||||||
} else {
|
} else {
|
||||||
outbound[key] = v;
|
dst[key] = v_src;
|
||||||
|
}
|
||||||
|
} else if (v_src.isArray()) {
|
||||||
|
if (key.startsWith("+")) {
|
||||||
|
auto key2 = SubStrAfter(key, "+");
|
||||||
|
auto v_dst = dst[key2];
|
||||||
|
auto v_src_arr = v_src.toArray();
|
||||||
|
auto v_dst_arr = v_dst.toArray();
|
||||||
|
QJSONARRAY_ADD(v_src_arr, v_dst_arr)
|
||||||
|
dst[key2] = v_src_arr;
|
||||||
|
} else if (key.endsWith("+")) {
|
||||||
|
auto key2 = SubStrBefore(key, "+");
|
||||||
|
auto v_dst = dst[key2];
|
||||||
|
auto v_src_arr = v_src.toArray();
|
||||||
|
auto v_dst_arr = v_dst.toArray();
|
||||||
|
QJSONARRAY_ADD(v_dst_arr, v_src_arr)
|
||||||
|
dst[key2] = v_dst_arr;
|
||||||
|
} else {
|
||||||
|
dst[key] = v_src;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outbound[key] = custom[key];
|
dst[key] = v_src;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,7 +86,7 @@ namespace NekoGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// apply custom config
|
// apply custom config
|
||||||
MergeJson(QString2QJsonObject(ent->bean->custom_config), result->coreConfig);
|
MergeJson(result->coreConfig, QString2QJsonObject(ent->bean->custom_config));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -76,7 +94,7 @@ namespace NekoGui {
|
|||||||
QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status) {
|
QString BuildChain(int chainId, const std::shared_ptr<BuildConfigStatus> &status) {
|
||||||
auto group = profileManager->GetGroup(status->ent->gid);
|
auto group = profileManager->GetGroup(status->ent->gid);
|
||||||
if (group == nullptr) {
|
if (group == nullptr) {
|
||||||
status->result->error = QString("This profile is not in any group, your data may be corrupted.");
|
status->result->error = QStringLiteral("This profile is not in any group, your data may be corrupted.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,11 +106,11 @@ namespace NekoGui {
|
|||||||
for (auto id: list) {
|
for (auto id: list) {
|
||||||
resolved += profileManager->GetProfile(id);
|
resolved += profileManager->GetProfile(id);
|
||||||
if (resolved.last() == nullptr) {
|
if (resolved.last() == nullptr) {
|
||||||
status->result->error = QString("chain missing ent: %1").arg(id);
|
status->result->error = QStringLiteral("chain missing ent: %1").arg(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (resolved.last()->type == "chain") {
|
if (resolved.last()->type == "chain") {
|
||||||
status->result->error = QString("chain in chain is not allowed: %1").arg(id);
|
status->result->error = QStringLiteral("chain in chain is not allowed: %1").arg(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +127,7 @@ namespace NekoGui {
|
|||||||
if (group->front_proxy_id >= 0) {
|
if (group->front_proxy_id >= 0) {
|
||||||
auto fEnt = profileManager->GetProfile(group->front_proxy_id);
|
auto fEnt = profileManager->GetProfile(group->front_proxy_id);
|
||||||
if (fEnt == nullptr) {
|
if (fEnt == nullptr) {
|
||||||
status->result->error = QString("front proxy ent not found.");
|
status->result->error = QStringLiteral("front proxy ent not found.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
ents += resolveChain(fEnt);
|
ents += resolveChain(fEnt);
|
||||||
@ -342,7 +360,7 @@ namespace NekoGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// apply custom outbound settings
|
// apply custom outbound settings
|
||||||
MergeJson(QString2QJsonObject(ent->bean->custom_outbound), outbound);
|
MergeJson(outbound, QString2QJsonObject(ent->bean->custom_outbound));
|
||||||
|
|
||||||
// Bypass Lookup for the first profile
|
// Bypass Lookup for the first profile
|
||||||
auto serverAddress = ent->bean->serverAddress;
|
auto serverAddress = ent->bean->serverAddress;
|
||||||
@ -486,7 +504,7 @@ namespace NekoGui {
|
|||||||
} else if (item.startsWith("keyword:")) {
|
} else if (item.startsWith("keyword:")) {
|
||||||
domain_keyword += item.replace("keyword:", "").toLower();
|
domain_keyword += item.replace("keyword:", "").toLower();
|
||||||
} else {
|
} else {
|
||||||
domain_full += item.toLower();
|
domain_subdomain += item.toLower();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -523,21 +541,22 @@ namespace NekoGui {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Direct
|
// Direct
|
||||||
auto directDNSAddress = dataStore->routing->direct_dns;
|
QJsonObject directObj{
|
||||||
if (!status->forTest) {
|
{"tag", "dns-direct"},
|
||||||
QJsonObject directObj{
|
{"address_resolver", "dns-local"},
|
||||||
{"tag", "dns-direct"},
|
{"strategy", dataStore->routing->direct_dns_strategy},
|
||||||
{"address_resolver", "dns-local"},
|
{"address", dataStore->routing->direct_dns},
|
||||||
{"strategy", dataStore->routing->direct_dns_strategy},
|
{"detour", "direct"},
|
||||||
{"address", directDNSAddress.replace("+local://", "://")},
|
};
|
||||||
{"detour", "direct"},
|
if (dataStore->routing->dns_final_out == "bypass") {
|
||||||
};
|
dnsServers.prepend(directObj);
|
||||||
if (dataStore->routing->dns_final_out == "bypass") {
|
} else {
|
||||||
dnsServers.prepend(directObj);
|
dnsServers.append(directObj);
|
||||||
} else {
|
|
||||||
dnsServers.append(directObj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
dnsRules.append(QJsonObject{
|
||||||
|
{"outbound", "any"},
|
||||||
|
{"server", "dns-direct"},
|
||||||
|
});
|
||||||
|
|
||||||
// block
|
// block
|
||||||
if (!status->forTest)
|
if (!status->forTest)
|
||||||
@ -687,7 +706,7 @@ namespace NekoGui {
|
|||||||
QJSONARRAY_ADD(routingRules, status->routingRules)
|
QJSONARRAY_ADD(routingRules, status->routingRules)
|
||||||
auto routeObj = QJsonObject{
|
auto routeObj = QJsonObject{
|
||||||
{"rules", routingRules},
|
{"rules", routingRules},
|
||||||
{"auto_detect_interface", dataStore->spmode_vpn},
|
{"auto_detect_interface", dataStore->spmode_vpn}, // TODO force enable?
|
||||||
{
|
{
|
||||||
"geoip",
|
"geoip",
|
||||||
QJsonObject{
|
QJsonObject{
|
||||||
@ -725,8 +744,8 @@ namespace NekoGui {
|
|||||||
|
|
||||||
QString WriteVPNSingBoxConfig() {
|
QString WriteVPNSingBoxConfig() {
|
||||||
// tun user rule
|
// tun user rule
|
||||||
auto match_out = dataStore->vpn_rule_white ? "nekobox-socks" : "direct";
|
auto match_out = dataStore->vpn_rule_white ? "neko-socks" : "direct";
|
||||||
auto no_match_out = dataStore->vpn_rule_white ? "direct" : "nekobox-socks";
|
auto no_match_out = dataStore->vpn_rule_white ? "direct" : "neko-socks";
|
||||||
|
|
||||||
QString process_name_rule = dataStore->vpn_rule_process.trimmed();
|
QString process_name_rule = dataStore->vpn_rule_process.trimmed();
|
||||||
if (!process_name_rule.isEmpty()) {
|
if (!process_name_rule.isEmpty()) {
|
||||||
|
|||||||
@ -42,7 +42,7 @@ namespace NekoGui {
|
|||||||
// Load Proxys
|
// Load Proxys
|
||||||
QList<int> delProfile;
|
QList<int> delProfile;
|
||||||
for (auto id: profilesIdOrder) {
|
for (auto id: profilesIdOrder) {
|
||||||
auto ent = LoadProxyEntity(QString("profiles/%1.json").arg(id));
|
auto ent = LoadProxyEntity(QStringLiteral("profiles/%1.json").arg(id));
|
||||||
// Corrupted profile?
|
// Corrupted profile?
|
||||||
if (ent == nullptr || ent->bean == nullptr || ent->bean->version == -114514) {
|
if (ent == nullptr || ent->bean == nullptr || ent->bean->version == -114514) {
|
||||||
delProfile << id;
|
delProfile << id;
|
||||||
@ -58,7 +58,7 @@ namespace NekoGui {
|
|||||||
auto loadedOrder = groupsTabOrder;
|
auto loadedOrder = groupsTabOrder;
|
||||||
groupsTabOrder = {};
|
groupsTabOrder = {};
|
||||||
for (auto id: groupsIdOrder) {
|
for (auto id: groupsIdOrder) {
|
||||||
auto ent = LoadGroup(QString("groups/%1.json").arg(id));
|
auto ent = LoadGroup(QStringLiteral("groups/%1.json").arg(id));
|
||||||
// Corrupted group?
|
// Corrupted group?
|
||||||
if (ent->id != id) {
|
if (ent->id != id) {
|
||||||
continue;
|
continue;
|
||||||
@ -103,7 +103,7 @@ namespace NekoGui {
|
|||||||
auto newId = i++;
|
auto newId = i++;
|
||||||
profile->id = newId;
|
profile->id = newId;
|
||||||
profile->gid = gidOld2New[gid];
|
profile->gid = gidOld2New[gid];
|
||||||
profile->fn = QString("profiles/%1.json").arg(newId);
|
profile->fn = QStringLiteral("profiles/%1.json").arg(newId);
|
||||||
profile->Save();
|
profile->Save();
|
||||||
newProfiles[newId] = profile;
|
newProfiles[newId] = profile;
|
||||||
newProfilesIdOrder << newId;
|
newProfilesIdOrder << newId;
|
||||||
@ -122,7 +122,7 @@ namespace NekoGui {
|
|||||||
auto group = groups[oldGid];
|
auto group = groups[oldGid];
|
||||||
QFile::remove(group->fn);
|
QFile::remove(group->fn);
|
||||||
group->id = newId;
|
group->id = newId;
|
||||||
group->fn = QString("groups/%1.json").arg(newId);
|
group->fn = QStringLiteral("groups/%1.json").arg(newId);
|
||||||
group->Save();
|
group->Save();
|
||||||
newGroups[newId] = group;
|
newGroups[newId] = group;
|
||||||
newGroupsIdOrder << newId;
|
newGroupsIdOrder << newId;
|
||||||
@ -227,7 +227,7 @@ namespace NekoGui {
|
|||||||
if (latency < 0) {
|
if (latency < 0) {
|
||||||
return QObject::tr("Unavailable");
|
return QObject::tr("Unavailable");
|
||||||
} else if (latency > 0) {
|
} else if (latency > 0) {
|
||||||
return UNICODE_LRO + QString("%1 ms").arg(latency);
|
return UNICODE_LRO + QStringLiteral("%1 ms").arg(latency);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ namespace NekoGui {
|
|||||||
profiles[ent->id] = ent;
|
profiles[ent->id] = ent;
|
||||||
profilesIdOrder.push_back(ent->id);
|
profilesIdOrder.push_back(ent->id);
|
||||||
|
|
||||||
ent->fn = QString("profiles/%1.json").arg(ent->id);
|
ent->fn = QStringLiteral("profiles/%1.json").arg(ent->id);
|
||||||
ent->Save();
|
ent->Save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -278,7 +278,7 @@ namespace NekoGui {
|
|||||||
if (dataStore->started_id == id) return;
|
if (dataStore->started_id == id) return;
|
||||||
profiles.erase(id);
|
profiles.erase(id);
|
||||||
profilesIdOrder.removeAll(id);
|
profilesIdOrder.removeAll(id);
|
||||||
QFile(QString("profiles/%1.json").arg(id)).remove();
|
QFile(QStringLiteral("profiles/%1.json").arg(id)).remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileManager::MoveProfile(const std::shared_ptr<ProxyEntity> &ent, int gid) {
|
void ProfileManager::MoveProfile(const std::shared_ptr<ProxyEntity> &ent, int gid) {
|
||||||
@ -342,7 +342,7 @@ namespace NekoGui {
|
|||||||
groupsIdOrder.push_back(ent->id);
|
groupsIdOrder.push_back(ent->id);
|
||||||
groupsTabOrder.push_back(ent->id);
|
groupsTabOrder.push_back(ent->id);
|
||||||
|
|
||||||
ent->fn = QString("groups/%1.json").arg(ent->id);
|
ent->fn = QStringLiteral("groups/%1.json").arg(ent->id);
|
||||||
ent->Save();
|
ent->Save();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -359,7 +359,7 @@ namespace NekoGui {
|
|||||||
groups.erase(gid);
|
groups.erase(gid);
|
||||||
groupsIdOrder.removeAll(gid);
|
groupsIdOrder.removeAll(gid);
|
||||||
groupsTabOrder.removeAll(gid);
|
groupsTabOrder.removeAll(gid);
|
||||||
QFile(QString("groups/%1.json").arg(gid)).remove();
|
QFile(QStringLiteral("groups/%1.json").arg(gid)).remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Group> ProfileManager::GetGroup(int id) {
|
std::shared_ptr<Group> ProfileManager::GetGroup(int id) {
|
||||||
|
|||||||
@ -29,12 +29,12 @@ namespace NekoGui_traffic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] QString DisplaySpeed() const {
|
[[nodiscard]] QString DisplaySpeed() const {
|
||||||
return UNICODE_LRO + QString("%1↑ %2↓").arg(ReadableSize(uplink_rate), ReadableSize(downlink_rate));
|
return UNICODE_LRO + QStringLiteral("%1↑ %2↓").arg(ReadableSize(uplink_rate), ReadableSize(downlink_rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] QString DisplayTraffic() const {
|
[[nodiscard]] QString DisplayTraffic() const {
|
||||||
if (downlink + uplink == 0) return "";
|
if (downlink + uplink == 0) return "";
|
||||||
return UNICODE_LRO + QString("%1↑ %2↓").arg(ReadableSize(uplink), ReadableSize(downlink));
|
return UNICODE_LRO + QStringLiteral("%1↑ %2↓").arg(ReadableSize(uplink), ReadableSize(downlink));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace NekoGui_traffic
|
} // namespace NekoGui_traffic
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace NekoGui_fmt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString AbstractBean::DisplayTypeAndName() {
|
QString AbstractBean::DisplayTypeAndName() {
|
||||||
return QString("[%1] %2").arg(DisplayType(), DisplayName());
|
return QStringLiteral("[%1] %2").arg(DisplayType(), DisplayName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractBean::ResolveDomainToIP(const std::function<void()> &onFinished) {
|
void AbstractBean::ResolveDomainToIP(const std::function<void()> &onFinished) {
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
#define WriteTempFile(fn, data) \
|
#define WriteTempFile(fn, data) \
|
||||||
QDir dir; \
|
QDir dir; \
|
||||||
if (!dir.exists("temp")) dir.mkdir("temp"); \
|
if (!dir.exists("temp")) dir.mkdir("temp"); \
|
||||||
QFile f(QString("temp/") + fn); \
|
QFile f(QStringLiteral("temp/") + fn); \
|
||||||
bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \
|
bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); \
|
||||||
if (ok) { \
|
if (ok) { \
|
||||||
f.write(data); \
|
f.write(data); \
|
||||||
@ -50,7 +50,7 @@ namespace NekoGui_fmt {
|
|||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!forceExternal && (proxy_type == proxy_TUIC || hopPort.trimmed().isEmpty())) {
|
if (!forceExternal) {
|
||||||
// sing-box support
|
// sing-box support
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace NekoGui_fmt {
|
|||||||
url.setScheme("http");
|
url.setScheme("http");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
url.setScheme(QString("socks%1").arg(socks_http_type));
|
url.setScheme(QStringLiteral("socks%1").arg(socks_http_type));
|
||||||
}
|
}
|
||||||
if (!name.isEmpty()) url.setFragment(name);
|
if (!name.isEmpty()) url.setFragment(name);
|
||||||
if (!username.isEmpty()) url.setUserName(username);
|
if (!username.isEmpty()) url.setUserName(username);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ require (
|
|||||||
github.com/libdns/cloudflare v0.1.1 // indirect
|
github.com/libdns/cloudflare v0.1.1 // indirect
|
||||||
github.com/libdns/libdns v0.2.2 // indirect
|
github.com/libdns/libdns v0.2.2 // indirect
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||||
|
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d // indirect
|
||||||
github.com/mholt/acmez v1.2.0 // indirect
|
github.com/mholt/acmez v1.2.0 // indirect
|
||||||
github.com/miekg/dns v1.1.59 // indirect
|
github.com/miekg/dns v1.1.59 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
|
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
|
||||||
@ -52,19 +53,18 @@ require (
|
|||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect
|
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect
|
||||||
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect
|
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect
|
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect
|
||||||
github.com/sagernet/quic-go v0.45.1-beta.2 // indirect
|
github.com/sagernet/quic-go v0.47.0-beta.2 // indirect
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||||
github.com/sagernet/sing v0.4.1 // indirect
|
github.com/sagernet/sing v0.4.3 // indirect
|
||||||
github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65 // indirect
|
github.com/sagernet/sing-dns v0.2.3 // indirect
|
||||||
github.com/sagernet/sing-mux v0.2.0 // indirect
|
github.com/sagernet/sing-mux v0.2.0 // indirect
|
||||||
github.com/sagernet/sing-quic v0.2.0-beta.12 // indirect
|
github.com/sagernet/sing-quic v0.2.2 // indirect
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6 // indirect
|
github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect
|
github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
|
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
|
||||||
github.com/sagernet/sing-tun v0.3.2 // indirect
|
github.com/sagernet/sing-tun v0.3.3 // indirect
|
||||||
github.com/sagernet/sing-vmess v0.1.8 // indirect
|
github.com/sagernet/sing-vmess v0.1.12 // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 // indirect
|
|
||||||
github.com/sagernet/utls v1.5.4 // indirect
|
github.com/sagernet/utls v1.5.4 // indirect
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect
|
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect
|
||||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect
|
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect
|
||||||
@ -80,16 +80,16 @@ require (
|
|||||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
||||||
golang.org/x/mod v0.18.0 // indirect
|
golang.org/x/mod v0.18.0 // indirect
|
||||||
golang.org/x/net v0.25.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.21.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
golang.org/x/text v0.16.0 // indirect
|
golang.org/x/text v0.18.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||||
google.golang.org/grpc v1.63.2 // indirect
|
google.golang.org/grpc v1.63.2 // indirect
|
||||||
google.golang.org/protobuf v1.33.0 // indirect
|
google.golang.org/protobuf v1.33.0 // indirect
|
||||||
lukechampine.com/blake3 v1.2.1 // indirect
|
lukechampine.com/blake3 v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace grpc_server => ../../grpc_server
|
replace grpc_server => ../../grpc_server
|
||||||
@ -98,7 +98,7 @@ replace github.com/matsuridayo/libneko => ../../../../libneko
|
|||||||
|
|
||||||
replace github.com/sagernet/sing-box => ../../../../sing-box
|
replace github.com/sagernet/sing-box => ../../../../sing-box
|
||||||
|
|
||||||
// replace github.com/sagernet/sing-quic => ../../../../sing-quic
|
replace github.com/sagernet/sing-quic => ../../../../sing-quic
|
||||||
|
|
||||||
// replace github.com/sagernet/sing => ../../../../sing
|
// replace github.com/sagernet/sing => ../../../../sing
|
||||||
|
|
||||||
|
|||||||
@ -94,6 +94,8 @@ github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
|||||||
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
|
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d h1:j9LtzkYstLFoNvXW824QQeN7Y26uPL5249kzWKbzO9U=
|
||||||
|
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts=
|
||||||
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||||
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||||
@ -125,33 +127,29 @@ github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y
|
|||||||
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0=
|
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0=
|
||||||
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk=
|
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk=
|
||||||
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/quic-go v0.45.1-beta.2 h1:zkEeCbhdFFkrxKcuIRBtXNKci/1t2J/39QSG/sPvlmc=
|
github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU=
|
||||||
github.com/sagernet/quic-go v0.45.1-beta.2/go.mod h1:+N3FqM9DAzOWfe64uxXuBejVJwX7DeW7BslzLO6N/xI=
|
github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk=
|
github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8=
|
||||||
github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
|
github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
|
||||||
github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65 h1:lcCe7E1csuyUA3RCvpFcIYOy6FIifDthKaCrUjLG4xA=
|
github.com/sagernet/sing-dns v0.2.3 h1:YzeBUn2tR38F7HtvGEQ0kLRLmZWMEgi/+7wqa4Twb1k=
|
||||||
github.com/sagernet/sing-dns v0.2.1-0.20240624030536-ca4a5f7afb65/go.mod h1:dArgyPZmK8+zDBVRMjV3r12zHgnTara0ahrWwSe/eQE=
|
github.com/sagernet/sing-dns v0.2.3/go.mod h1:BJpJv6XLnrUbSyIntOT6DG9FW0f4fETmPAHvNjOprLg=
|
||||||
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
||||||
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||||
github.com/sagernet/sing-quic v0.2.0-beta.12 h1:BhvA5mmrDFEyDUQB5eeu+9UhF+ieyuNJ5Rsb0dAG3QY=
|
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||||
github.com/sagernet/sing-quic v0.2.0-beta.12/go.mod h1:YVpLfVi8BvYM7NMrjmnvcRm3E8iMETf1gFQmTQDN9jI=
|
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||||
github.com/sagernet/sing-tun v0.3.2 h1:z0bLUT/YXH9RrJS9DsIpB0Bb9afl2hVJOmHd0zA3HJY=
|
github.com/sagernet/sing-tun v0.3.3 h1:LZnQNmfGcNG2KPTPkLgc+Lo7k606QJVkPp2DnjriwUk=
|
||||||
github.com/sagernet/sing-tun v0.3.2/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ=
|
github.com/sagernet/sing-tun v0.3.3/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ=
|
||||||
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg=
|
||||||
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 h1:z3SJQhVyU63FT26Wn/UByW6b7q8QKB0ZkPqsyqcz2PI=
|
|
||||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6/go.mod h1:73xRZuxwkFk4aiLw28hG8W6o9cr2UPrGL9pdY2UTbvY=
|
|
||||||
github.com/sagernet/utls v1.5.4 h1:KmsEGbB2dKUtCNC+44NwAdNAqnqQ6GA4pTO0Yik56co=
|
github.com/sagernet/utls v1.5.4 h1:KmsEGbB2dKUtCNC+44NwAdNAqnqQ6GA4pTO0Yik56co=
|
||||||
github.com/sagernet/utls v1.5.4/go.mod h1:CTGxPWExIloRipK3XFpYv0OVyhO8kk3XCGW/ieyTh1s=
|
github.com/sagernet/utls v1.5.4/go.mod h1:CTGxPWExIloRipK3XFpYv0OVyhO8kk3XCGW/ieyTh1s=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYAScomNAVpTfbHFpxqJpvwuhxSRi+g6z7gZhABs=
|
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYAScomNAVpTfbHFpxqJpvwuhxSRi+g6z7gZhABs=
|
||||||
@ -229,8 +227,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -245,15 +243,15 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -296,5 +294,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
|
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
||||||
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||||
|
|||||||
@ -18,6 +18,16 @@ popd
|
|||||||
|
|
||||||
####
|
####
|
||||||
|
|
||||||
|
if [ ! -d "sing-quic" ]; then
|
||||||
|
git clone --no-checkout https://github.com/MatsuriDayo/sing-quic.git
|
||||||
|
fi
|
||||||
|
pushd sing-quic
|
||||||
|
git checkout "$COMMIT_SING_QUIC"
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
####
|
||||||
|
|
||||||
if [ ! -d "libneko" ]; then
|
if [ ! -d "libneko" ]; then
|
||||||
git clone --no-checkout https://github.com/MatsuriDayo/libneko.git
|
git clone --no-checkout https://github.com/MatsuriDayo/libneko.git
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
export COMMIT_SING_BOX="cf36758f11b7c144e1211801753cc91f06ff2906"
|
export COMMIT_SING_BOX="06557f6cef23160668122a17a818b378b5a216b5"
|
||||||
|
export COMMIT_SING_QUIC="b49ce60d9b3622d5238fee96bfd3c5f6e3915b42"
|
||||||
export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b"
|
export COMMIT_LIBNEKO="1c47a3af71990a7b2192e03292b4d246c308ef0b"
|
||||||
|
|||||||
@ -51,7 +51,7 @@ namespace NekoGui_network {
|
|||||||
for (const auto &err: errors) {
|
for (const auto &err: errors) {
|
||||||
error_str << err.errorString();
|
error_str << err.errorString();
|
||||||
}
|
}
|
||||||
MW_show_log(QString("SSL Errors: %1 %2").arg(error_str.join(","), NekoGui::dataStore->sub_insecure ? "(Ignored)" : ""));
|
MW_show_log(QStringLiteral("SSL Errors: %1 %2").arg(error_str.join(","), NekoGui::dataStore->sub_insecure ? "(Ignored)" : ""));
|
||||||
});
|
});
|
||||||
// Wait for response
|
// Wait for response
|
||||||
auto abortTimer = new QTimer;
|
auto abortTimer = new QTimer;
|
||||||
|
|||||||
@ -247,7 +247,6 @@ namespace NekoGui {
|
|||||||
_add(new configItem("theme", &theme, itemType::string));
|
_add(new configItem("theme", &theme, itemType::string));
|
||||||
_add(new configItem("custom_inbound", &custom_inbound, itemType::string));
|
_add(new configItem("custom_inbound", &custom_inbound, itemType::string));
|
||||||
_add(new configItem("custom_route", &custom_route_global, itemType::string));
|
_add(new configItem("custom_route", &custom_route_global, itemType::string));
|
||||||
_add(new configItem("v2ray_asset_dir", &v2ray_asset_dir, itemType::string));
|
|
||||||
_add(new configItem("sub_use_proxy", &sub_use_proxy, itemType::boolean));
|
_add(new configItem("sub_use_proxy", &sub_use_proxy, itemType::boolean));
|
||||||
_add(new configItem("remember_id", &remember_id, itemType::integer));
|
_add(new configItem("remember_id", &remember_id, itemType::integer));
|
||||||
_add(new configItem("remember_enable", &remember_enable, itemType::boolean));
|
_add(new configItem("remember_enable", &remember_enable, itemType::boolean));
|
||||||
@ -350,7 +349,7 @@ namespace NekoGui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString Routing::DisplayRouting() const {
|
QString Routing::DisplayRouting() const {
|
||||||
return QString("[Proxy] %1\n[Proxy] %2\n[Direct] %3\n[Direct] %4\n[Block] %5\n[Block] %6\n[Default Outbound] %7\n[DNS] %8")
|
return QStringLiteral("[Proxy] %1\n[Proxy] %2\n[Direct] %3\n[Direct] %4\n[Block] %5\n[Block] %6\n[Default Outbound] %7\n[DNS] %8")
|
||||||
.arg(SplitLinesSkipSharp(proxy_domain).join(","), 10)
|
.arg(SplitLinesSkipSharp(proxy_domain).join(","), 10)
|
||||||
.arg(SplitLinesSkipSharp(proxy_ip).join(","), 10)
|
.arg(SplitLinesSkipSharp(proxy_ip).join(","), 10)
|
||||||
.arg(SplitLinesSkipSharp(direct_domain).join(","), 10)
|
.arg(SplitLinesSkipSharp(direct_domain).join(","), 10)
|
||||||
@ -416,16 +415,13 @@ namespace NekoGui {
|
|||||||
// System Utils
|
// System Utils
|
||||||
|
|
||||||
QString FindCoreAsset(const QString &name) {
|
QString FindCoreAsset(const QString &name) {
|
||||||
QStringList search{NekoGui::dataStore->v2ray_asset_dir};
|
QStringList search{};
|
||||||
search << QApplication::applicationDirPath();
|
search << QApplication::applicationDirPath();
|
||||||
search << "/usr/share/sing-geoip";
|
search << "/usr/share/sing-geoip";
|
||||||
search << "/usr/share/sing-geosite";
|
search << "/usr/share/sing-geosite";
|
||||||
search << "/usr/share/xray";
|
search << "/usr/share/sing-box";
|
||||||
search << "/usr/local/share/xray";
|
search << "/usr/lib/nekobox";
|
||||||
search << "/opt/xray";
|
search << "/usr/share/nekobox";
|
||||||
search << "/usr/share/v2ray";
|
|
||||||
search << "/usr/local/share/v2ray";
|
|
||||||
search << "/opt/v2ray";
|
|
||||||
for (const auto &dir: search) {
|
for (const auto &dir: search) {
|
||||||
if (dir.isEmpty()) continue;
|
if (dir.isEmpty()) continue;
|
||||||
QFileInfo asset(dir + "/" + name);
|
QFileInfo asset(dir + "/" + name);
|
||||||
|
|||||||
@ -17,5 +17,5 @@ namespace NekoGui {
|
|||||||
bool IsAdmin();
|
bool IsAdmin();
|
||||||
} // namespace NekoGui
|
} // namespace NekoGui
|
||||||
|
|
||||||
#define ROUTES_PREFIX_NAME QString("routes_box")
|
#define ROUTES_PREFIX_NAME QStringLiteral("routes_box")
|
||||||
#define ROUTES_PREFIX QString(ROUTES_PREFIX_NAME + "/")
|
#define ROUTES_PREFIX QString(ROUTES_PREFIX_NAME + "/")
|
||||||
|
|||||||
@ -107,7 +107,6 @@ namespace NekoGui {
|
|||||||
int mux_concurrency = 8;
|
int mux_concurrency = 8;
|
||||||
bool mux_default_on = false;
|
bool mux_default_on = false;
|
||||||
QString theme = "0";
|
QString theme = "0";
|
||||||
QString v2ray_asset_dir = "";
|
|
||||||
int language = 0;
|
int language = 0;
|
||||||
QString mw_size = "";
|
QString mw_size = "";
|
||||||
bool check_include_pre = false;
|
bool check_include_pre = false;
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
4.0-beta2-2024-07-05
|
4.0.1-2024-12-12
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
{
|
{
|
||||||
"tag": "dns-remote",
|
"tag": "dns-remote",
|
||||||
"address": "8.8.8.8",
|
"address": "8.8.8.8",
|
||||||
"detour": "nekoray-socks"
|
"detour": "neko-socks"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "dns-direct",
|
"tag": "dns-direct",
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"outbounds": [
|
"outbounds": [
|
||||||
{
|
{
|
||||||
"type": "socks",
|
"type": "socks",
|
||||||
"tag": "nekoray-socks",
|
"tag": "neko-socks",
|
||||||
"udp_fragment": true,
|
"udp_fragment": true,
|
||||||
//%SOCKS_USER_PASS%
|
//%SOCKS_USER_PASS%
|
||||||
"server": "127.0.0.1",
|
"server": "127.0.0.1",
|
||||||
|
|||||||
@ -205,7 +205,7 @@ namespace NekoGui_rpc {
|
|||||||
|
|
||||||
#define NOT_OK \
|
#define NOT_OK \
|
||||||
*rpcOK = false; \
|
*rpcOK = false; \
|
||||||
onError(QString("QNetworkReply::NetworkError code: %1\n").arg(status));
|
onError(QStringLiteral("QNetworkReply::NetworkError code: %1\n").arg(status));
|
||||||
|
|
||||||
void Client::Exit() {
|
void Client::Exit() {
|
||||||
libcore::EmptyReq request;
|
libcore::EmptyReq request;
|
||||||
|
|||||||
@ -141,13 +141,7 @@ namespace NekoGui_sys {
|
|||||||
|
|
||||||
void CoreProcess::Start() {
|
void CoreProcess::Start() {
|
||||||
show_stderr = false;
|
show_stderr = false;
|
||||||
// set extra env
|
// cwd: same as GUI, at ./config
|
||||||
auto v2ray_asset_dir = NekoGui::FindCoreAsset("geoip.dat");
|
|
||||||
if (!v2ray_asset_dir.isEmpty()) {
|
|
||||||
v2ray_asset_dir = QFileInfo(v2ray_asset_dir).absolutePath();
|
|
||||||
env << "XRAY_LOCATION_ASSET=" + v2ray_asset_dir;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
ExternalProcess::Start();
|
ExternalProcess::Start();
|
||||||
write((NekoGui::dataStore->core_token + "\n").toUtf8());
|
write((NekoGui::dataStore->core_token + "\n").toUtf8());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ LONG __stdcall CreateCrashHandler(EXCEPTION_POINTERS *pException) {
|
|||||||
}
|
}
|
||||||
// 创建消息提示
|
// 创建消息提示
|
||||||
QMessageBox::warning(NULL, "Application crashed",
|
QMessageBox::warning(NULL, "Application crashed",
|
||||||
QString("ErrorCode: %1 ErrorAddr:%2 ErrorFlag: %3 ErrorPara: %4\nVersion: %5\nDump file at %6")
|
QStringLiteral("ErrorCode: %1 ErrorAddr:%2 ErrorFlag: %3 ErrorPara: %4\nVersion: %5\nDump file at %6")
|
||||||
.arg(errCode)
|
.arg(errCode)
|
||||||
.arg(errAddr)
|
.arg(errAddr)
|
||||||
.arg(errFlag)
|
.arg(errFlag)
|
||||||
|
|||||||
@ -63,14 +63,6 @@
|
|||||||
<source>Custom Inbound</source>
|
<source>Custom Inbound</source>
|
||||||
<translation>ورودی سفارشی</translation>
|
<translation>ورودی سفارشی</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<source>Asset Location</source>
|
|
||||||
<translation>مکان دارایی</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Default: dir of "nekoray"</source>
|
|
||||||
<translation type="unfinished">مسیر پیش فرض "nekoray"</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>Concurrent</source>
|
<source>Concurrent</source>
|
||||||
<translation>هم زمان</translation>
|
<translation>هم زمان</translation>
|
||||||
@ -1500,6 +1492,10 @@ End: %2</source>
|
|||||||
<source>Stop Testing</source>
|
<source>Stop Testing</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>URL Test</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ProxyItem</name>
|
<name>ProxyItem</name>
|
||||||
@ -1640,6 +1636,10 @@ Direct: %2</source>
|
|||||||
<source>Default</source>
|
<source>Default</source>
|
||||||
<translation type="unfinished">پیش فرض</translation>
|
<translation type="unfinished">پیش فرض</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>The last speed test did not exit completely, please wait. If it persists, please restart the program.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
||||||
|
|||||||
@ -107,14 +107,6 @@
|
|||||||
<source>Core</source>
|
<source>Core</source>
|
||||||
<translation>Ядро</translation>
|
<translation>Ядро</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<source>Asset Location</source>
|
|
||||||
<translation>Расположение файлов</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Default: dir of "nekoray"</source>
|
|
||||||
<translation>По умолчанию: текущая папка nekoray</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>Select</source>
|
<source>Select</source>
|
||||||
<translation>Выбрать</translation>
|
<translation>Выбрать</translation>
|
||||||
@ -1506,6 +1498,10 @@ End: %2</source>
|
|||||||
<source>Stop Testing</source>
|
<source>Stop Testing</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>URL Test</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ProxyItem</name>
|
<name>ProxyItem</name>
|
||||||
@ -1653,6 +1649,10 @@ Release note:
|
|||||||
<source>Default</source>
|
<source>Default</source>
|
||||||
<translation>По умолчанию</translation>
|
<translation>По умолчанию</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>The last speed test did not exit completely, please wait. If it persists, please restart the program.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
||||||
|
|||||||
@ -63,14 +63,6 @@
|
|||||||
<source>Custom Inbound</source>
|
<source>Custom Inbound</source>
|
||||||
<translation>自定义入站</translation>
|
<translation>自定义入站</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<source>Asset Location</source>
|
|
||||||
<translation>资源文件路径</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Default: dir of "nekoray"</source>
|
|
||||||
<translation>默认值:和 nekoray 同路径</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>Concurrent</source>
|
<source>Concurrent</source>
|
||||||
<translation>并发</translation>
|
<translation>并发</translation>
|
||||||
@ -1496,7 +1488,7 @@ Split by line.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>In and Out IP</source>
|
<source>In and Out IP</source>
|
||||||
<translation>入口出口IP</translation>
|
<translation>入口出口 IP</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Test Options</source>
|
<source>Test Options</source>
|
||||||
@ -1506,6 +1498,10 @@ Split by line.</source>
|
|||||||
<source>Stop Testing</source>
|
<source>Stop Testing</source>
|
||||||
<translation>停止测试</translation>
|
<translation>停止测试</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>URL Test</source>
|
||||||
|
<translation>URL 测试</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ProxyItem</name>
|
<name>ProxyItem</name>
|
||||||
@ -1653,6 +1649,10 @@ Release note:
|
|||||||
<source>Default</source>
|
<source>Default</source>
|
||||||
<translation>默认</translation>
|
<translation>默认</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>The last speed test did not exit completely, please wait. If it persists, please restart the program.</source>
|
||||||
|
<translation>上次速度测试未完全退出,请等待。如果问题仍然存在,请重新启动程序。</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
<name>Qv2ray::ui::widgets::AutoCompleteTextEdit</name>
|
||||||
|
|||||||
@ -59,7 +59,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
|
|
||||||
// Common
|
// Common
|
||||||
|
|
||||||
ui->log_level->addItems(QString("trace debug info warn error fatal panic").split(" "));
|
ui->log_level->addItems(QStringLiteral("trace debug info warn error fatal panic").split(" "));
|
||||||
ui->mux_protocol->addItems({"h2mux", "smux", "yamux"});
|
ui->mux_protocol->addItems({"h2mux", "smux", "yamux"});
|
||||||
|
|
||||||
refresh_auth();
|
refresh_auth();
|
||||||
@ -155,7 +155,6 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
// Core
|
// Core
|
||||||
|
|
||||||
ui->groupBox_core->setTitle(software_core_name);
|
ui->groupBox_core->setTitle(software_core_name);
|
||||||
ui->core_v2ray_asset->setText(NekoGui::dataStore->v2ray_asset_dir);
|
|
||||||
//
|
//
|
||||||
CACHE.extraCore = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map);
|
CACHE.extraCore = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map);
|
||||||
if (!CACHE.extraCore.contains("naive")) CACHE.extraCore.insert("naive", "");
|
if (!CACHE.extraCore.contains("naive")) CACHE.extraCore.insert("naive", "");
|
||||||
@ -167,16 +166,6 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s));
|
extra_core_layout->addWidget(new ExtraCoreWidget(&CACHE.extraCore, s));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
connect(ui->core_v2ray_asset, &QLineEdit::textChanged, this, [=] {
|
|
||||||
CACHE.needRestart = true;
|
|
||||||
});
|
|
||||||
connect(ui->core_v2ray_asset_pick, &QPushButton::clicked, this, [=] {
|
|
||||||
auto fn = QFileDialog::getExistingDirectory(this, tr("Select"), QDir::currentPath(),
|
|
||||||
QFileDialog::Option::ShowDirsOnly | QFileDialog::Option::ReadOnly);
|
|
||||||
if (!fn.isEmpty()) {
|
|
||||||
ui->core_v2ray_asset->setText(fn);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(ui->extra_core_add, &QPushButton::clicked, this, [=] {
|
connect(ui->extra_core_add, &QPushButton::clicked, this, [=] {
|
||||||
bool ok;
|
bool ok;
|
||||||
auto s = QInputDialog::getText(nullptr, tr("Add"),
|
auto s = QInputDialog::getText(nullptr, tr("Add"),
|
||||||
@ -278,7 +267,6 @@ void DialogBasicSettings::accept() {
|
|||||||
|
|
||||||
// Core
|
// Core
|
||||||
|
|
||||||
NekoGui::dataStore->v2ray_asset_dir = ui->core_v2ray_asset->text();
|
|
||||||
NekoGui::dataStore->extraCore->core_map = QJsonObject2QString(CACHE.extraCore, true);
|
NekoGui::dataStore->extraCore->core_map = QJsonObject2QString(CACHE.extraCore, true);
|
||||||
|
|
||||||
// Mux
|
// Mux
|
||||||
@ -293,7 +281,7 @@ void DialogBasicSettings::accept() {
|
|||||||
NekoGui::dataStore->utlsFingerprint = ui->utlsFingerprint->currentText();
|
NekoGui::dataStore->utlsFingerprint = ui->utlsFingerprint->currentText();
|
||||||
|
|
||||||
// 关闭连接统计,停止刷新前清空记录。
|
// 关闭连接统计,停止刷新前清空记录。
|
||||||
if (NekoGui::dataStore->traffic_loop_interval == 0 || NekoGui::dataStore->connection_statistics == false) {
|
if (NekoGui::dataStore->traffic_loop_interval == 0 || !NekoGui::dataStore->connection_statistics) {
|
||||||
MW_dialog_message("", "ClearConnectionList");
|
MW_dialog_message("", "ClearConnectionList");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -566,39 +566,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="assest_group" native="true">
|
<widget class="QWidget" name="assest_group" native="true">
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_12">
|
|
||||||
<property name="text">
|
|
||||||
<string>Asset Location</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="MyLineEdit" name="core_v2ray_asset">
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>Default: dir of "nekoray"</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QPushButton" name="core_v2ray_asset_pick">
|
|
||||||
<property name="text">
|
|
||||||
<string>Select</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string notr="true">Loglevel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QComboBox" name="log_level">
|
<widget class="QComboBox" name="log_level">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
@ -608,14 +576,21 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Multiplex (mux)</string>
|
<string>Multiplex (mux)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Loglevel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="mux_protocol"/>
|
<widget class="QComboBox" name="mux_protocol"/>
|
||||||
|
|||||||
@ -25,7 +25,7 @@ DialogManageRoutes::DialogManageRoutes(QWidget *parent) : QDialog(parent), ui(ne
|
|||||||
//
|
//
|
||||||
ui->outbound_domain_strategy->addItems(Preset::SingBox::DomainStrategy);
|
ui->outbound_domain_strategy->addItems(Preset::SingBox::DomainStrategy);
|
||||||
ui->domainStrategyCombo->addItems(Preset::SingBox::DomainStrategy);
|
ui->domainStrategyCombo->addItems(Preset::SingBox::DomainStrategy);
|
||||||
qsValue += QString("prefer_ipv4 prefer_ipv6 ipv4_only ipv6_only").split(" ");
|
qsValue += QStringLiteral("prefer_ipv4 prefer_ipv6 ipv4_only ipv6_only").split(" ");
|
||||||
ui->dns_object->setPlaceholderText(DecodeB64IfValid("ewogICJzZXJ2ZXJzIjogW10sCiAgInJ1bGVzIjogW10sCiAgImZpbmFsIjogIiIsCiAgInN0cmF0ZWd5IjogIiIsCiAgImRpc2FibGVfY2FjaGUiOiBmYWxzZSwKICAiZGlzYWJsZV9leHBpcmUiOiBmYWxzZSwKICAiaW5kZXBlbmRlbnRfY2FjaGUiOiBmYWxzZSwKICAicmV2ZXJzZV9tYXBwaW5nIjogZmFsc2UsCiAgImZha2VpcCI6IHt9Cn0="));
|
ui->dns_object->setPlaceholderText(DecodeB64IfValid("ewogICJzZXJ2ZXJzIjogW10sCiAgInJ1bGVzIjogW10sCiAgImZpbmFsIjogIiIsCiAgInN0cmF0ZWd5IjogIiIsCiAgImRpc2FibGVfY2FjaGUiOiBmYWxzZSwKICAiZGlzYWJsZV9leHBpcmUiOiBmYWxzZSwKICAiaW5kZXBlbmRlbnRfY2FjaGUiOiBmYWxzZSwKICAicmV2ZXJzZV9tYXBwaW5nIjogZmFsc2UsCiAgImZha2VpcCI6IHt9Cn0="));
|
||||||
dnsHelpDocumentUrl = "https://sing-box.sagernet.org/configuration/dns/";
|
dnsHelpDocumentUrl = "https://sing-box.sagernet.org/configuration/dns/";
|
||||||
//
|
//
|
||||||
|
|||||||
@ -118,7 +118,7 @@ void EditCustom::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
|||||||
auto command = QStringList{extR->program};
|
auto command = QStringList{extR->program};
|
||||||
command += extR->arguments;
|
command += extR->arguments;
|
||||||
auto btn = QMessageBox::information(this, tr("Preview config"),
|
auto btn = QMessageBox::information(this, tr("Preview config"),
|
||||||
QString("Command: %1\n\n%2").arg(QStringList2Command(command), extR->config_export),
|
QStringLiteral("Command: %1\n\n%2").arg(QStringList2Command(command), extR->config_export),
|
||||||
"OK", "Copy", "", 0, 0);
|
"OK", "Copy", "", 0, 0);
|
||||||
if (btn == 1) {
|
if (btn == 1) {
|
||||||
QApplication::clipboard()->setText(extR->config_export);
|
QApplication::clipboard()->setText(extR->config_export);
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
#include "3rdparty/qrcodegen.hpp"
|
#include "3rdparty/qrcodegen.hpp"
|
||||||
#include "3rdparty/VT100Parser.hpp"
|
#include "3rdparty/VT100Parser.hpp"
|
||||||
#include "3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp"
|
#include "3rdparty/qv2ray/v2/components/proxy/QvProxyConfigurator.hpp"
|
||||||
#include "3rdparty/qv2ray/v2/ui/LogHighlighter.hpp"
|
|
||||||
|
|
||||||
#ifndef NKR_NO_ZXING
|
#ifndef NKR_NO_ZXING
|
||||||
#include "3rdparty/ZxingQtReader.hpp"
|
#include "3rdparty/ZxingQtReader.hpp"
|
||||||
@ -102,12 +101,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
ui->toolButton_server->setMenu(ui->menu_server);
|
ui->toolButton_server->setMenu(ui->menu_server);
|
||||||
ui->menubar->setVisible(false);
|
ui->menubar->setVisible(false);
|
||||||
connect(ui->toolButton_document, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://matsuridayo.github.io/")); });
|
connect(ui->toolButton_document, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://matsuridayo.github.io/")); });
|
||||||
connect(ui->toolButton_ads, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://matsuricom.pages.dev/")); });
|
connect(ui->toolButton_ads, &QToolButton::clicked, this, [=] { QDesktopServices::openUrl(QUrl("https://neko-box.pages.dev/喵")); });
|
||||||
connect(ui->toolButton_update, &QToolButton::clicked, this, [=] { runOnNewThread([=] { CheckUpdate(); }); });
|
connect(ui->toolButton_update, &QToolButton::clicked, this, [=] { runOnNewThread([=] { CheckUpdate(); }); });
|
||||||
|
connect(ui->toolButton_url_test, &QToolButton::clicked, this, [=] { speedtest_current_group(1, true); });
|
||||||
|
|
||||||
// Setup log UI
|
// Setup log UI
|
||||||
ui->splitter->restoreState(DecodeB64IfValid(NekoGui::dataStore->splitter_state));
|
ui->splitter->restoreState(DecodeB64IfValid(NekoGui::dataStore->splitter_state));
|
||||||
new SyntaxHighlighter(false, qvLogDocument);
|
|
||||||
qvLogDocument->setUndoRedoEnabled(false);
|
qvLogDocument->setUndoRedoEnabled(false);
|
||||||
ui->masterLogBrowser->setUndoRedoEnabled(false);
|
ui->masterLogBrowser->setUndoRedoEnabled(false);
|
||||||
ui->masterLogBrowser->setDocument(qvLogDocument);
|
ui->masterLogBrowser->setDocument(qvLogDocument);
|
||||||
@ -335,10 +334,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
neko_set_spmode_vpn(false);
|
neko_set_spmode_vpn(false);
|
||||||
});
|
});
|
||||||
connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); });
|
connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); });
|
||||||
connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0); });
|
connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0, false); });
|
||||||
connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1); });
|
connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1, false); });
|
||||||
connect(ui->menu_full_test, &QAction::triggered, this, [=]() { speedtest_current_group(2); });
|
connect(ui->menu_full_test, &QAction::triggered, this, [=]() { speedtest_current_group(2, false); });
|
||||||
connect(ui->menu_stop_testing, &QAction::triggered, this, [=]() { speedtest_current_group(114514); });
|
connect(ui->menu_stop_testing, &QAction::triggered, this, [=]() { speedtest_current_group(114514, false); });
|
||||||
//
|
//
|
||||||
auto set_selected_or_group = [=](int mode) {
|
auto set_selected_or_group = [=](int mode) {
|
||||||
// 0=group 1=select 2=unknown(menu is hide)
|
// 0=group 1=select 2=unknown(menu is hide)
|
||||||
@ -479,7 +478,7 @@ void MainWindow::show_group(int gid) {
|
|||||||
|
|
||||||
auto group = NekoGui::profileManager->GetGroup(gid);
|
auto group = NekoGui::profileManager->GetGroup(gid);
|
||||||
if (group == nullptr) {
|
if (group == nullptr) {
|
||||||
MessageBoxWarning(tr("Error"), QString("No such group: %1").arg(gid));
|
MessageBoxWarning(tr("Error"), QStringLiteral("No such group: %1").arg(gid));
|
||||||
NekoGui::dataStore->refreshing_group = false;
|
NekoGui::dataStore->refreshing_group = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -630,7 +629,7 @@ void MainWindow::on_commitDataRequest() {
|
|||||||
//
|
//
|
||||||
if (!isMaximized()) {
|
if (!isMaximized()) {
|
||||||
auto olds = NekoGui::dataStore->mw_size;
|
auto olds = NekoGui::dataStore->mw_size;
|
||||||
auto news = QString("%1x%2").arg(size().width()).arg(size().height());
|
auto news = QStringLiteral("%1x%2").arg(size().width()).arg(size().height());
|
||||||
if (olds != news) {
|
if (olds != news) {
|
||||||
NekoGui::dataStore->mw_size = news;
|
NekoGui::dataStore->mw_size = news;
|
||||||
}
|
}
|
||||||
@ -833,12 +832,12 @@ void MainWindow::refresh_status(const QString &traffic_update) {
|
|||||||
|
|
||||||
if (last_test_time.addSecs(2) < QTime::currentTime()) {
|
if (last_test_time.addSecs(2) < QTime::currentTime()) {
|
||||||
auto txt = running == nullptr ? tr("Not Running")
|
auto txt = running == nullptr ? tr("Not Running")
|
||||||
: QString("[%1] %2").arg(group_name, running->bean->DisplayName()).left(30);
|
: QStringLiteral("[%1] %2").arg(group_name, running->bean->DisplayName()).left(30);
|
||||||
ui->label_running->setText(txt);
|
ui->label_running->setText(txt);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
auto display_socks = DisplayAddress(NekoGui::dataStore->inbound_address, NekoGui::dataStore->inbound_socks_port);
|
auto display_socks = DisplayAddress(NekoGui::dataStore->inbound_address, NekoGui::dataStore->inbound_socks_port);
|
||||||
auto inbound_txt = QString("Mixed: %1").arg(display_socks);
|
auto inbound_txt = QStringLiteral("Mixed: %1").arg(display_socks);
|
||||||
ui->label_inbound->setText(inbound_txt);
|
ui->label_inbound->setText(inbound_txt);
|
||||||
//
|
//
|
||||||
ui->checkBox_VPN->setChecked(NekoGui::dataStore->spmode_vpn);
|
ui->checkBox_VPN->setChecked(NekoGui::dataStore->spmode_vpn);
|
||||||
@ -1168,7 +1167,7 @@ void MainWindow::on_menu_profile_debug_info_triggered() {
|
|||||||
if (ents.count() != 1) return;
|
if (ents.count() != 1) return;
|
||||||
auto btn = QMessageBox::information(this, software_name, ents.first()->ToJsonBytes(), "OK", "Edit", "Reload", 0, 0);
|
auto btn = QMessageBox::information(this, software_name, ents.first()->ToJsonBytes(), "OK", "Edit", "Reload", 0, 0);
|
||||||
if (btn == 1) {
|
if (btn == 1) {
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(QString("profiles/%1.json").arg(ents.first()->id)).absoluteFilePath()));
|
QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(QStringLiteral("profiles/%1.json").arg(ents.first()->id)).absoluteFilePath()));
|
||||||
} else if (btn == 2) {
|
} else if (btn == 2) {
|
||||||
NekoGui::dataStore->Load();
|
NekoGui::dataStore->Load();
|
||||||
NekoGui::profileManager->LoadManager();
|
NekoGui::profileManager->LoadManager();
|
||||||
@ -1209,23 +1208,23 @@ void MainWindow::on_menu_export_config_triggered() {
|
|||||||
if (ent->bean->DisplayCoreType() != software_core_name) return;
|
if (ent->bean->DisplayCoreType() != software_core_name) return;
|
||||||
|
|
||||||
auto result = BuildConfig(ent, false, true);
|
auto result = BuildConfig(ent, false, true);
|
||||||
QString config_core = QJsonObject2QString(result->coreConfig, true);
|
QString config_core = QJsonObject2QString(result->coreConfig, false);
|
||||||
QApplication::clipboard()->setText(config_core);
|
QApplication::clipboard()->setText(config_core);
|
||||||
|
|
||||||
QMessageBox msg(QMessageBox::Information, tr("Config copied"), config_core);
|
QMessageBox msg(QMessageBox::Information, tr("Config copied"), tr("Config copied"));
|
||||||
msg.addButton("Copy core config", QMessageBox::YesRole);
|
msg.addButton("Copy core config", QMessageBox::YesRole);
|
||||||
msg.addButton("Copy test config", QMessageBox::YesRole);
|
msg.addButton("Copy test config", QMessageBox::NoRole);
|
||||||
msg.addButton(QMessageBox::Ok);
|
msg.addButton(QMessageBox::Ok);
|
||||||
msg.setEscapeButton(QMessageBox::Ok);
|
msg.setEscapeButton(QMessageBox::Ok);
|
||||||
msg.setDefaultButton(QMessageBox::Ok);
|
msg.setDefaultButton(QMessageBox::Ok);
|
||||||
auto ret = msg.exec();
|
auto ret = msg.exec();
|
||||||
if (ret == 0) {
|
if (ret == 2) {
|
||||||
result = BuildConfig(ent, false, false);
|
result = BuildConfig(ent, false, false);
|
||||||
config_core = QJsonObject2QString(result->coreConfig, true);
|
config_core = QJsonObject2QString(result->coreConfig, false);
|
||||||
QApplication::clipboard()->setText(config_core);
|
QApplication::clipboard()->setText(config_core);
|
||||||
} else if (ret == 1) {
|
} else if (ret == 3) {
|
||||||
result = BuildConfig(ent, true, false);
|
result = BuildConfig(ent, true, false);
|
||||||
config_core = QJsonObject2QString(result->coreConfig, true);
|
config_core = QJsonObject2QString(result->coreConfig, false);
|
||||||
QApplication::clipboard()->setText(config_core);
|
QApplication::clipboard()->setText(config_core);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1801,7 +1800,7 @@ bool MainWindow::StartVPNProcess() {
|
|||||||
//
|
//
|
||||||
vpn_process->setProcessChannelMode(QProcess::ForwardedChannels);
|
vpn_process->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
vpn_process->start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges")
|
vpn_process->start("osascript", {"-e", QStringLiteral("do shell script \"%1\" with administrator privileges")
|
||||||
.arg("bash " + scriptPath)});
|
.arg("bash " + scriptPath)});
|
||||||
#else
|
#else
|
||||||
vpn_process->start("pkexec", {"bash", scriptPath});
|
vpn_process->start("pkexec", {"bash", scriptPath});
|
||||||
@ -1824,7 +1823,7 @@ bool MainWindow::StopVPNProcess(bool unconditional) {
|
|||||||
#else
|
#else
|
||||||
QProcess p;
|
QProcess p;
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
p.start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges")
|
p.start("osascript", {"-e", QStringLiteral("do shell script \"%1\" with administrator privileges")
|
||||||
.arg("pkill -2 -U 0 nekobox_core")});
|
.arg("pkill -2 -U 0 nekobox_core")});
|
||||||
#else
|
#else
|
||||||
if (unconditional) {
|
if (unconditional) {
|
||||||
|
|||||||
@ -185,7 +185,7 @@ private:
|
|||||||
|
|
||||||
static void setup_grpc();
|
static void setup_grpc();
|
||||||
|
|
||||||
void speedtest_current_group(int mode);
|
void speedtest_current_group(int mode, bool test_group);
|
||||||
|
|
||||||
void speedtest_current();
|
void speedtest_current();
|
||||||
|
|
||||||
|
|||||||
@ -205,6 +205,19 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="toolButton_url_test">
|
||||||
|
<property name="text">
|
||||||
|
<string>URL Test</string>
|
||||||
|
</property>
|
||||||
|
<property name="popupMode">
|
||||||
|
<enum>QToolButton::InstantPopup</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolButtonStyle">
|
||||||
|
<enum>Qt::ToolButtonTextUnderIcon</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -665,7 +678,7 @@
|
|||||||
<string notr="true">Tcp Ping</string>
|
<string notr="true">Tcp Ping</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Shift+T</string>
|
<string notr="true">Ctrl+Alt+T</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="menu_url_test">
|
<action name="menu_url_test">
|
||||||
@ -673,7 +686,7 @@
|
|||||||
<string notr="true">Url Test</string>
|
<string notr="true">Url Test</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Shift+U</string>
|
<string notr="true">Ctrl+Alt+U</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="menu_clear_test_result">
|
<action name="menu_clear_test_result">
|
||||||
@ -681,7 +694,7 @@
|
|||||||
<string>Clear Test Result</string>
|
<string>Clear Test Result</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Shift+C</string>
|
<string notr="true">Ctrl+Alt+C</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="menu_export_config">
|
<action name="menu_export_config">
|
||||||
@ -726,7 +739,7 @@
|
|||||||
<string>Remove Duplicates</string>
|
<string>Remove Duplicates</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Shift+D</string>
|
<string notr="true">Ctrl+Alt+D</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionfake">
|
<action name="actionfake">
|
||||||
@ -774,7 +787,7 @@
|
|||||||
<string>Remove Unavailable</string>
|
<string>Remove Unavailable</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Shift+R</string>
|
<string notr="true">Ctrl+Alt+R</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="menu_full_test">
|
<action name="menu_full_test">
|
||||||
@ -782,7 +795,7 @@
|
|||||||
<string>Full Test</string>
|
<string>Full Test</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Shift+F</string>
|
<string notr="true">Ctrl+Alt+F</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="menu_hotkey_settings">
|
<action name="menu_hotkey_settings">
|
||||||
@ -803,7 +816,7 @@
|
|||||||
<string>Copy links of selected (Neko Links)</string>
|
<string>Copy links of selected (Neko Links)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Alt+C</string>
|
<string notr="true">Ctrl+N</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionfake_2">
|
<action name="actionfake_2">
|
||||||
@ -859,7 +872,7 @@
|
|||||||
<string>Resolve domain</string>
|
<string>Resolve domain</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string notr="true">Ctrl+Shift+I</string>
|
<string notr="true">Ctrl+Alt+I</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="menu_vpn_settings">
|
<action name="menu_vpn_settings">
|
||||||
@ -902,6 +915,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Stop Testing</string>
|
<string>Stop Testing</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string notr="true">Ctrl+Alt+S</string>
|
||||||
|
</property>
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
|||||||
@ -58,8 +58,14 @@ void MainWindow::setup_grpc() {
|
|||||||
inline bool speedtesting = false;
|
inline bool speedtesting = false;
|
||||||
inline QList<QThread *> speedtesting_threads = {};
|
inline QList<QThread *> speedtesting_threads = {};
|
||||||
|
|
||||||
void MainWindow::speedtest_current_group(int mode) {
|
void MainWindow::speedtest_current_group(int mode, bool test_group) {
|
||||||
|
if (speedtesting) {
|
||||||
|
MessageBoxWarning(software_name, QObject::tr("The last speed test did not exit completely, please wait. If it persists, please restart the program."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto profiles = get_selected_or_group();
|
auto profiles = get_selected_or_group();
|
||||||
|
if (test_group) profiles = NekoGui::profileManager->CurrentGroup()->ProfilesWithOrder();
|
||||||
if (profiles.isEmpty()) return;
|
if (profiles.isEmpty()) return;
|
||||||
auto group = NekoGui::profileManager->CurrentGroup();
|
auto group = NekoGui::profileManager->CurrentGroup();
|
||||||
if (group->archive) return;
|
if (group->archive) return;
|
||||||
@ -75,11 +81,6 @@ void MainWindow::speedtest_current_group(int mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NKR_NO_GRPC
|
#ifndef NKR_NO_GRPC
|
||||||
if (speedtesting) {
|
|
||||||
MessageBoxWarning(software_name, "The last speed test did not exit completely, please wait. If it persists, please restart the program.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList full_test_flags;
|
QStringList full_test_flags;
|
||||||
if (mode == libcore::FullTest) {
|
if (mode == libcore::FullTest) {
|
||||||
auto w = new QDialog(this);
|
auto w = new QDialog(this);
|
||||||
@ -150,7 +151,7 @@ void MainWindow::speedtest_current_group(int mode) {
|
|||||||
//
|
//
|
||||||
libcore::TestReq req;
|
libcore::TestReq req;
|
||||||
req.set_mode((libcore::TestMode) mode);
|
req.set_mode((libcore::TestMode) mode);
|
||||||
req.set_timeout(5000);
|
req.set_timeout(10 * 1000);
|
||||||
req.set_url(NekoGui::dataStore->test_latency_url.toStdString());
|
req.set_url(NekoGui::dataStore->test_latency_url.toStdString());
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -181,7 +182,7 @@ void MainWindow::speedtest_current_group(int mode) {
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
auto config = new libcore::LoadConfigReq;
|
auto config = new libcore::LoadConfigReq;
|
||||||
config->set_core_config(QJsonObject2QString(c->coreConfig, true).toStdString());
|
config->set_core_config(QJsonObject2QString(c->coreConfig, false).toStdString());
|
||||||
req.set_allocated_config(config);
|
req.set_allocated_config(config);
|
||||||
req.set_in_address(profile->bean->serverAddress.toStdString());
|
req.set_in_address(profile->bean->serverAddress.toStdString());
|
||||||
|
|
||||||
@ -238,6 +239,7 @@ void MainWindow::speedtest_current_group(int mode) {
|
|||||||
lock_return.lock();
|
lock_return.lock();
|
||||||
lock_return.unlock();
|
lock_return.unlock();
|
||||||
speedtesting = false;
|
speedtesting = false;
|
||||||
|
MW_show_log(QObject::tr("Speedtest finished."));
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -250,7 +252,7 @@ void MainWindow::speedtest_current() {
|
|||||||
runOnNewThread([=] {
|
runOnNewThread([=] {
|
||||||
libcore::TestReq req;
|
libcore::TestReq req;
|
||||||
req.set_mode(libcore::UrlTest);
|
req.set_mode(libcore::UrlTest);
|
||||||
req.set_timeout(5000);
|
req.set_timeout(10 * 1000);
|
||||||
req.set_url(NekoGui::dataStore->test_latency_url.toStdString());
|
req.set_url(NekoGui::dataStore->test_latency_url.toStdString());
|
||||||
|
|
||||||
bool rpcOK;
|
bool rpcOK;
|
||||||
@ -262,12 +264,12 @@ void MainWindow::speedtest_current() {
|
|||||||
|
|
||||||
runOnUiThread([=] {
|
runOnUiThread([=] {
|
||||||
if (!result.error().empty()) {
|
if (!result.error().empty()) {
|
||||||
MW_show_log(QString("UrlTest error: %1").arg(result.error().c_str()));
|
MW_show_log(QStringLiteral("UrlTest error: %1").arg(result.error().c_str()));
|
||||||
}
|
}
|
||||||
if (latency <= 0) {
|
if (latency <= 0) {
|
||||||
ui->label_running->setText(tr("Test Result") + ": " + tr("Unavailable"));
|
ui->label_running->setText(tr("Test Result") + ": " + tr("Unavailable"));
|
||||||
} else if (latency > 0) {
|
} else if (latency > 0) {
|
||||||
ui->label_running->setText(tr("Test Result") + ": " + QString("%1 ms").arg(latency));
|
ui->label_running->setText(tr("Test Result") + ": " + QStringLiteral("%1 ms").arg(latency));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -306,7 +308,7 @@ void MainWindow::neko_start(int _id) {
|
|||||||
auto neko_start_stage2 = [=] {
|
auto neko_start_stage2 = [=] {
|
||||||
#ifndef NKR_NO_GRPC
|
#ifndef NKR_NO_GRPC
|
||||||
libcore::LoadConfigReq req;
|
libcore::LoadConfigReq req;
|
||||||
req.set_core_config(QJsonObject2QString(result->coreConfig, true).toStdString());
|
req.set_core_config(QJsonObject2QString(result->coreConfig, false).toStdString());
|
||||||
req.set_enable_nekoray_connections(NekoGui::dataStore->connection_statistics);
|
req.set_enable_nekoray_connections(NekoGui::dataStore->connection_statistics);
|
||||||
if (NekoGui::dataStore->traffic_loop_interval > 0) {
|
if (NekoGui::dataStore->traffic_loop_interval > 0) {
|
||||||
req.add_stats_outbounds("proxy");
|
req.add_stats_outbounds("proxy");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user