├── .github └── workflows │ ├── build-simpleplugin-qt6.yml │ ├── build-simpleplugin.yml │ └── hashfile.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CommandPlugin.cpp ├── CommandPlugin.hpp ├── assets └── qv2ray.png ├── core ├── CommandConfig.hpp ├── EventHandler.cpp └── EventHandler.hpp ├── resx.qrc └── ui ├── CommandPluginSettings.cpp ├── CommandPluginSettings.hpp ├── CommandPluginSettings.ui └── GUIInterface.hpp /.github/workflows/build-simpleplugin-qt6.yml: -------------------------------------------------------------------------------- 1 | name: QvPlugin Build Action Qt6 - cmake 2 | 3 | on: 4 | push: 5 | release: 6 | types: [prereleased] 7 | 8 | jobs: 9 | build: 10 | strategy: 11 | matrix: 12 | qt_version: [6.0.0] 13 | platform: [ubuntu-20.04, macos-latest, windows-latest] 14 | include: 15 | - platform: windows-latest 16 | qtarch: win64_msvc2019_64 17 | fail-fast: false 18 | 19 | runs-on: ${{ matrix.platform }} 20 | env: 21 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 22 | steps: 23 | - name: Get the version 24 | id: get_version 25 | shell: bash 26 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) 27 | - name: Get Plugin Name 28 | id: get_name 29 | shell: bash 30 | run: echo ::set-output name=NAME::QvPlugin-Command 31 | - name: Checking out sources 32 | uses: actions/checkout@master 33 | - name: Install Python 3.7 version 34 | uses: actions/setup-python@v1 35 | with: 36 | python-version: '3.7' 37 | - name: Restoring submodules 38 | run: git submodule update --init 39 | # ========================================================================================================= 40 | - name: Install MSVC compiler 41 | if: matrix.platform == 'windows-latest' 42 | uses: ilammy/msvc-dev-cmd@v1 43 | with: 44 | toolset: 14.2 45 | arch: x64 46 | - name: Cache Qt 47 | id: cache-qt 48 | uses: actions/cache@v1 49 | with: 50 | path: ../Qt 51 | key: QtCache-${{ matrix.platform }}-${{ matrix.qt_version }} 52 | - name: Installing Qt - ${{ matrix.arch }} 53 | uses: jurplel/install-qt-action@v2 54 | with: 55 | version: ${{ matrix.qt_version }} 56 | arch: ${{ matrix.qtarch }} 57 | cached: ${{ steps.cache-qt.outputs.cache-hit }} 58 | # ========================================================================================================= 59 | - name: Linux - ${{ matrix.qt_version }} - Build preparation - Install Packages 60 | if: matrix.platform == 'ubuntu-20.04' 61 | run: | 62 | sudo apt update 63 | sudo apt install -y libgl-dev libx11-dev libxkbcommon-x11-dev libxcb-image0-dev libxcb-icccm4-dev libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 64 | # ========================================================================================================= Generate MakeFile and Build 65 | - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build 66 | shell: bash 67 | if: matrix.platform == 'windows-latest' 68 | env: 69 | CC: cl.exe 70 | CXX: cl.exe 71 | run: | 72 | mkdir build 73 | cd build 74 | cmake .. -DCMAKE_BUILD_TYPE=Release -A x64 -DQVPLUGIN_USE_QT6=ON 75 | cmake --build . --parallel $(nproc) --config Release 76 | # -------------------------------------------------------- 77 | - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build 78 | shell: bash 79 | if: matrix.platform == 'macos-latest' 80 | run: | 81 | mkdir build 82 | cd build 83 | cmake .. -DCMAKE_BUILD_TYPE=Release -DQVPLUGIN_USE_QT6=ON 84 | cmake --build . --parallel $(sysctl -n hw.logicalcpu) 85 | # -------------------------------------------------------- 86 | - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build 87 | if: matrix.platform == 'ubuntu-20.04' 88 | shell: bash 89 | env: 90 | CC: gcc-7 91 | CXX: g++-7 92 | CXXFLAGS: -fno-sized-deallocation 93 | run: | 94 | mkdir build 95 | cd build 96 | cmake .. -DCMAKE_BUILD_TYPE=Release -DQVPLUGIN_USE_QT6=ON 97 | cmake --build . --parallel $(nproc) 98 | # ========================================================================================================= Deployments 99 | - name: Win - ${{ matrix.qt_version }} - Uploading artifact 100 | if: matrix.platform == 'windows-latest' 101 | uses: actions/upload-artifact@master 102 | with: 103 | name: ${{ steps.get_name.outputs.NAME }}-${{ github.sha }}.Windows.Qt${{ matrix.qt_version }}.dll 104 | path: build/Release/${{ steps.get_name.outputs.NAME }}.dll 105 | - name: Win - ${{ matrix.qt_version }} - Upload binaries to release 106 | uses: svenstaro/upload-release-action@v1-release 107 | if: github.event_name == 'release' && matrix.platform == 'windows-latest' 108 | with: 109 | repo_token: ${{ secrets.GITHUB_TOKEN }} 110 | file: build/Release/${{ steps.get_name.outputs.NAME }}.dll 111 | asset_name: ${{ steps.get_name.outputs.NAME }}.${{ steps.get_version.outputs.VERSION }}.Windows.Qt6.dll 112 | tag: ${{ github.ref }} 113 | overwrite: true 114 | # -------------------------------------------------------- 115 | - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact 116 | if: matrix.platform == 'macos-latest' 117 | uses: actions/upload-artifact@master 118 | with: 119 | name: ${{ steps.get_name.outputs.NAME }}-${{ github.sha }}.macOS.Qt${{ matrix.qt_version }}.so 120 | path: build/lib${{ steps.get_name.outputs.NAME }}.so 121 | - name: macOS - ${{ matrix.qt_version }} - Upload binaries to release 122 | uses: svenstaro/upload-release-action@v1-release 123 | if: github.event_name == 'release' && matrix.platform == 'macos-latest' 124 | with: 125 | repo_token: ${{ secrets.GITHUB_TOKEN }} 126 | file: build/lib${{ steps.get_name.outputs.NAME }}.so 127 | asset_name: ${{ steps.get_name.outputs.NAME }}.${{ steps.get_version.outputs.VERSION }}.macOS.Qt6.so 128 | tag: ${{ github.ref }} 129 | overwrite: true 130 | # -------------------------------------------------------- 131 | - name: Linux - ${{ matrix.qt_version }} - Uploading artifact 132 | if: matrix.platform == 'ubuntu-20.04' 133 | uses: actions/upload-artifact@master 134 | with: 135 | name: ${{ steps.get_name.outputs.NAME }}-${{ github.sha }}.Linux.Qt${{ matrix.qt_version }}.so 136 | path: build/lib${{ steps.get_name.outputs.NAME }}.so 137 | - name: Linux - ${{ matrix.qt_version }} - Upload binaries to release 138 | uses: svenstaro/upload-release-action@v1-release 139 | if: github.event_name == 'release' && matrix.platform == 'ubuntu-20.04' 140 | with: 141 | repo_token: ${{ secrets.GITHUB_TOKEN }} 142 | file: build/lib${{ steps.get_name.outputs.NAME }}.so 143 | asset_name: ${{ steps.get_name.outputs.NAME }}.${{ steps.get_version.outputs.VERSION }}.Linux.Qt6.so 144 | tag: ${{ github.ref }} 145 | overwrite: true 146 | -------------------------------------------------------------------------------- /.github/workflows/build-simpleplugin.yml: -------------------------------------------------------------------------------- 1 | name: QvPlugin Build Action - cmake 2 | 3 | on: 4 | push: 5 | release: 6 | types: [prereleased] 7 | 8 | jobs: 9 | build: 10 | strategy: 11 | matrix: 12 | qt_version: [5.11.3] 13 | platform: [ubuntu-16.04, macos-latest, windows-latest] 14 | arch: [x86, x64] 15 | include: 16 | - platform: windows-latest 17 | arch: x86 18 | qtarch: win32_msvc2015 19 | cmakearch: Win32 20 | - platform: windows-latest 21 | arch: x64 22 | qtarch: win64_msvc2015_64 23 | cmakearch: x64 24 | exclude: 25 | - platform: ubuntu-16.04 26 | arch: x86 27 | - platform: macos-latest 28 | arch: x86 29 | fail-fast: false 30 | 31 | runs-on: ${{ matrix.platform }} 32 | env: 33 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 34 | steps: 35 | - name: Get the version 36 | id: get_version 37 | shell: bash 38 | run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) 39 | - name: Get Plugin Name 40 | id: get_name 41 | shell: bash 42 | run: echo ::set-output name=NAME::QvPlugin-Command 43 | - name: Checking out sources 44 | uses: actions/checkout@master 45 | - name: Install Python 3.7 version 46 | uses: actions/setup-python@v1 47 | with: 48 | python-version: '3.7' 49 | architecture: ${{ matrix.arch }} 50 | - name: Restoring submodules 51 | run: git submodule update --init 52 | # ========================================================================================================= 53 | - name: Install MSVC compiler 54 | if: matrix.platform == 'windows-latest' 55 | uses: ilammy/msvc-dev-cmd@v1 56 | with: 57 | toolset: 14.2 58 | arch: ${{ matrix.arch }} 59 | - name: Cache Qt 60 | id: cache-qt 61 | uses: actions/cache@v1 62 | with: 63 | path: ../Qt 64 | key: QtCache-${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.qt_version }}-${{ matrix.qtarch }} 65 | - name: Installing Qt - ${{ matrix.arch }} 66 | uses: jurplel/install-qt-action@v2.5.3 67 | with: 68 | version: ${{ matrix.qt_version }} 69 | arch: ${{ matrix.qtarch }} 70 | mirror: 'http://mirrors.ocf.berkeley.edu/qt/' 71 | cached: ${{ steps.cache-qt.outputs.cache-hit }} 72 | # ========================================================================================================= Generate MakeFile and Build 73 | - name: Windows - ${{ matrix.qt_version }} - Generate Dependencies and Build 74 | shell: bash 75 | if: matrix.platform == 'windows-latest' 76 | env: 77 | CC: cl.exe 78 | CXX: cl.exe 79 | run: | 80 | mkdir build 81 | cd build 82 | cmake .. -DCMAKE_BUILD_TYPE=Release -A ${{ matrix.cmakearch }} 83 | cmake --build . --parallel $(nproc) --config Release 84 | # -------------------------------------------------------- 85 | - name: macOS - ${{ matrix.qt_version }} - Generate Dependencies and Build 86 | shell: bash 87 | if: matrix.platform == 'macos-latest' 88 | run: | 89 | mkdir build 90 | cd build 91 | cmake .. -DCMAKE_BUILD_TYPE=Release 92 | cmake --build . --parallel $(sysctl -n hw.logicalcpu) 93 | # -------------------------------------------------------- 94 | - name: Linux - ${{ matrix.qt_version }} - Generate Dependencies and Build 95 | if: matrix.platform == 'ubuntu-16.04' 96 | shell: bash 97 | env: 98 | CC: gcc-7 99 | CXX: g++-7 100 | CXXFLAGS: -fno-sized-deallocation 101 | run: | 102 | mkdir build 103 | cd build 104 | cmake .. -DCMAKE_BUILD_TYPE=Release 105 | cmake --build . --parallel $(nproc) 106 | # ========================================================================================================= Deployments 107 | - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Uploading artifact 108 | if: matrix.platform == 'windows-latest' 109 | uses: actions/upload-artifact@master 110 | with: 111 | name: ${{ steps.get_name.outputs.NAME }}-${{ github.sha }}.Windows-${{ matrix.arch }}.qt${{ matrix.qt_version }}.dll 112 | path: build/Release/${{ steps.get_name.outputs.NAME }}.dll 113 | - name: Win-${{ matrix.arch }} - ${{ matrix.qt_version }} - Upload binaries to release 114 | uses: svenstaro/upload-release-action@v1-release 115 | if: github.event_name == 'release' && matrix.platform == 'windows-latest' 116 | with: 117 | repo_token: ${{ secrets.GITHUB_TOKEN }} 118 | file: build/Release/${{ steps.get_name.outputs.NAME }}.dll 119 | asset_name: ${{ steps.get_name.outputs.NAME }}.${{ steps.get_version.outputs.VERSION }}.Windows-${{ matrix.arch }}.dll 120 | tag: ${{ github.ref }} 121 | overwrite: true 122 | # -------------------------------------------------------- 123 | - name: macOS - ${{ matrix.qt_version }} - Uploading Artifact 124 | if: matrix.platform == 'macos-latest' 125 | uses: actions/upload-artifact@master 126 | with: 127 | name: ${{ steps.get_name.outputs.NAME }}-${{ github.sha }}.macOS-${{ matrix.arch }}.qt${{ matrix.qt_version }}.so 128 | path: build/lib${{ steps.get_name.outputs.NAME }}.so 129 | - name: macOS - ${{ matrix.qt_version }} - Upload binaries to release 130 | uses: svenstaro/upload-release-action@v1-release 131 | if: github.event_name == 'release' && matrix.platform == 'macos-latest' 132 | with: 133 | repo_token: ${{ secrets.GITHUB_TOKEN }} 134 | file: build/lib${{ steps.get_name.outputs.NAME }}.so 135 | asset_name: ${{ steps.get_name.outputs.NAME }}.${{ steps.get_version.outputs.VERSION }}.macOS-${{ matrix.arch }}.so 136 | tag: ${{ github.ref }} 137 | overwrite: true 138 | # -------------------------------------------------------- 139 | - name: Linux - ${{ matrix.qt_version }} - Uploading artifact 140 | if: matrix.platform == 'ubuntu-16.04' 141 | uses: actions/upload-artifact@master 142 | with: 143 | name: ${{ steps.get_name.outputs.NAME }}-${{ github.sha }}.linux-${{ matrix.arch }}.qt${{ matrix.qt_version }}.so 144 | path: build/lib${{ steps.get_name.outputs.NAME }}.so 145 | - name: Linux - ${{ matrix.qt_version }} - Upload binaries to release 146 | uses: svenstaro/upload-release-action@v1-release 147 | if: github.event_name == 'release' && matrix.platform == 'ubuntu-16.04' 148 | with: 149 | repo_token: ${{ secrets.GITHUB_TOKEN }} 150 | file: build/lib${{ steps.get_name.outputs.NAME }}.so 151 | asset_name: ${{ steps.get_name.outputs.NAME }}.${{ steps.get_version.outputs.VERSION }}.linux-${{ matrix.arch }}.so 152 | tag: ${{ github.ref }} 153 | overwrite: true 154 | -------------------------------------------------------------------------------- /.github/workflows/hashfile.yml: -------------------------------------------------------------------------------- 1 | name: Update release files hash 2 | 3 | on: 4 | release: 5 | types: [edited] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | env: 11 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 12 | steps: 13 | - run: echo ::set-env name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3) 14 | shell: bash 15 | - run: echo ::set-env name=REPOSITORY_NAME::$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}') 16 | shell: bash 17 | - name: Checking out sources 18 | uses: actions/checkout@master 19 | - name: Hash File 20 | shell: bash 21 | run: | 22 | wget -O release.info https://api.github.com/repos/Qv2ray/${REPOSITORY_NAME}/releases/tags/${VERSION} 23 | cat ./release.info | jq -r ".assets | .[] | .browser_download_url" > download.list 24 | cat ./release.info | jq -r ".assets | .[] | { uploader_id: .uploader.login, asset_name: .name }" > assets.info.json 25 | mkdir files 26 | cd files 27 | for x in $(cat ../download.list); do 28 | wget "$x"; 29 | done; 30 | rm assets.info.json || true 31 | rm sha256.list || true 32 | sha256sum ./* > ../sha256.list 33 | - name: Upload metadata to release 34 | uses: svenstaro/upload-release-action@v1-release 35 | with: 36 | repo_token: ${{ secrets.GITHUB_TOKEN }} 37 | file: assets.info.json 38 | asset_name: assets.info.json 39 | tag: ${{ github.ref }} 40 | overwrite: true 41 | - name: Upload metadata to release 42 | uses: svenstaro/upload-release-action@v1-release 43 | with: 44 | repo_token: ${{ secrets.GITHUB_TOKEN }} 45 | file: sha256.list 46 | asset_name: sha256.list 47 | tag: ${{ github.ref }} 48 | overwrite: true 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | build/ 3 | 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "interface"] 2 | path = interface 3 | url = https://github.com/Qv2ray/QvPlugin-Interface 4 | [submodule "lib/QJsonStruct"] 5 | path = lib/QJsonStruct 6 | url = https://github.com/Qv2ray/QJsonStruct 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(QvPlugin-Command) 2 | cmake_minimum_required(VERSION 3.1.0) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | 6 | if(CMAKE_VERSION VERSION_LESS "3.7.0") 7 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 8 | endif() 9 | 10 | set(CMAKE_AUTOMOC ON) 11 | set(CMAKE_AUTOUIC ON) 12 | set(CMAKE_AUTORCC ON) 13 | 14 | option(QVPLUGIN_USE_QT6 "Use Qt6") 15 | if(QVPLUGIN_USE_QT6) 16 | set(QV_QT_LIBNAME Qt6) 17 | else() 18 | set(QV_QT_LIBNAME Qt5) 19 | endif() 20 | find_package(${QV_QT_LIBNAME} COMPONENTS Core Widgets Gui REQUIRED) 21 | 22 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 23 | 24 | set(QVPLUGIN_INTERFACE_INCLUDE_DIR "interface/") 25 | include(interface/QvPluginInterface.cmake) 26 | include(interface/QvGUIPluginInterface.cmake) 27 | include_directories(${QVPLUGIN_INTERFACE_INCLUDE_DIR}) 28 | 29 | add_library(${PROJECT_NAME} MODULE 30 | CommandPlugin.hpp 31 | CommandPlugin.cpp 32 | core/EventHandler.cpp 33 | core/EventHandler.hpp 34 | core/CommandConfig.hpp 35 | ui/GUIInterface.hpp 36 | ui/CommandPluginSettings.cpp 37 | ui/CommandPluginSettings.hpp 38 | ui/CommandPluginSettings.ui 39 | lib/QJsonStruct/QJsonStruct.hpp 40 | resx.qrc 41 | ${QVPLUGIN_INTERFACE_HEADERS} 42 | ${QVGUIPLUGIN_INTERFACE_HEADERS} 43 | ) 44 | 45 | if(APPLE) 46 | add_custom_command(TARGET ${PROJECT_NAME} 47 | POST_BUILD 48 | COMMAND ${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/" $) 49 | endif() 50 | 51 | target_link_libraries(${PROJECT_NAME} 52 | ${QV_QT_LIBNAME}::Core 53 | ${QV_QT_LIBNAME}::Gui 54 | ${QV_QT_LIBNAME}::Widgets) 55 | 56 | install(TARGETS ${PROJECT_NAME} DESTINATION share/qv2ray/plugins) 57 | -------------------------------------------------------------------------------- /CommandPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandPlugin.hpp" 2 | 3 | #include "ui/CommandPluginSettings.hpp" 4 | #include "ui/GUIInterface.hpp" 5 | 6 | bool CommandPlugin::InitializePlugin(const QString &, const QJsonObject &conf) 7 | { 8 | Qv2rayInterface::UpdateSettings(conf); 9 | CommandPluginInstance = this; 10 | eventHandler = std::make_shared(); 11 | guiInterface = new CommandGUIInterface(); 12 | return true; 13 | } 14 | -------------------------------------------------------------------------------- /CommandPlugin.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "QvPluginInterface.hpp" 4 | #include "core/CommandConfig.hpp" 5 | #include "core/EventHandler.hpp" 6 | 7 | #include 8 | #include 9 | 10 | using namespace Qv2rayPlugin; 11 | 12 | class CommandPlugin 13 | : public QObject 14 | , public Qv2rayInterface 15 | { 16 | Q_INTERFACES(Qv2rayPlugin::Qv2rayInterface) 17 | Q_PLUGIN_METADATA(IID Qv2rayInterface_IID) 18 | Q_OBJECT 19 | public: 20 | // 21 | // Basic metainfo of this plugin 22 | const QvPluginMetadata GetMetadata() const override 23 | { 24 | return QvPluginMetadata{ 25 | "Qv2ray Command Plugin", // 26 | "Qv2ray Workgroup", // 27 | "qvplugin_command", // 28 | "Run any command when an event from Qv2ray occurs.", // 29 | "v3.0.0", // 30 | "Qv2ray/QvPlugin-Command", // 31 | { 32 | COMPONENT_EVENT_HANDLER, // 33 | COMPONENT_GUI // 34 | }, 35 | UPDATE_GITHUB_RELEASE // 36 | }; 37 | } 38 | bool InitializePlugin(const QString &, const QJsonObject &) override; 39 | 40 | signals: 41 | void PluginLog(const QString &) const override; 42 | void PluginErrorMessageBox(const QString &, const QString &) const override; 43 | }; 44 | 45 | DECLARE_PLUGIN_INSTANCE(CommandPlugin); 46 | -------------------------------------------------------------------------------- /assets/qv2ray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qv2ray/QvPlugin-Command/8f8147c7591d8b6c88aebd01087eb64d0a77537c/assets/qv2ray.png -------------------------------------------------------------------------------- /core/CommandConfig.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "lib/QJsonStruct/QJsonStruct.hpp" 3 | class CommandPluginConfig 4 | { 5 | public: 6 | QString beforeConnection; 7 | QString afterConnection; 8 | QString beforeDisConnection; 9 | QString afterDisConnection; 10 | // 11 | QString connectionCreated; 12 | QString connectionRenamed; 13 | QString connectionUpdated; 14 | QString connectionDeleted; 15 | // 16 | QString setSystemProxy; 17 | QString clearSystemProxy; 18 | // 19 | JSONSTRUCT_REGISTER(CommandPluginConfig, // 20 | F(beforeConnection, afterConnection, beforeDisConnection, afterDisConnection), // 21 | F(connectionCreated, connectionRenamed, connectionUpdated, connectionDeleted), // 22 | F(setSystemProxy, clearSystemProxy)) 23 | }; 24 | -------------------------------------------------------------------------------- /core/EventHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "EventHandler.hpp" 2 | 3 | #include "CommandPlugin.hpp" 4 | 5 | #include 6 | 7 | #if QT_VERSION_MAJOR >= 6 8 | using QRegExp = QRegularExpression; 9 | #define SkipEmpty Qt::SkipEmptyParts 10 | #else 11 | #define SkipEmpty QString::SkipEmptyParts 12 | #endif 13 | 14 | using namespace Qv2rayPlugin; 15 | SimpleEventHandler::SimpleEventHandler() : Qv2rayPlugin::PluginEventHandler(){}; 16 | QvPlugin_EventHandler(SimpleEventHandler, Connectivity) 17 | { 18 | /// 19 | /// Variables: 20 | /// $$DISPLAYNAME 21 | /// $$INBOUND_inboundProtocol 22 | /// --> port for that protocol, (e.g. $INBOUND_http as HTTP port) 23 | /// 24 | const auto settings = CommandPluginConfig::fromJson(CommandPluginInstance->GetSettngs()); 25 | 26 | QStringList actions; 27 | switch (pluginEvent.eventType) 28 | { 29 | case Events::Connectivity::Connected: 30 | { 31 | actions << settings.afterConnection.split(QRegExp("[\r\n]"), SkipEmpty); 32 | break; 33 | } 34 | case Events::Connectivity::Connecting: 35 | { 36 | actions << settings.beforeConnection.split(QRegExp("[\r\n]"), SkipEmpty); 37 | break; 38 | } 39 | case Events::Connectivity::Disconnected: 40 | { 41 | actions << settings.afterDisConnection.split(QRegExp("[\r\n]"), SkipEmpty); 42 | break; 43 | } 44 | case Events::Connectivity::Disconnecting: 45 | { 46 | actions << settings.beforeDisConnection.split(QRegExp("[\r\n]"), SkipEmpty); 47 | break; 48 | } 49 | } 50 | for (const auto &action : actions) 51 | { 52 | auto _command = action; 53 | _command.replace("$$DISPLAYNAME", pluginEvent.displayName); 54 | for (const auto &protocol : pluginEvent.inboundPorts.keys()) 55 | { 56 | _command.replace("$$INBOUND_" + protocol, QString::number(pluginEvent.inboundPorts[protocol])); 57 | } 58 | bool detached = _command.contains("$$CALL"); 59 | _command.replace("$$CALL", ""); 60 | if (detached) 61 | { 62 | auto returnvalue = QProcess::execute(_command); 63 | if (returnvalue != 0) 64 | { 65 | CommandPluginInstance->PluginLog("Failed to execute command : \"" + action + "\""); 66 | } 67 | } 68 | else 69 | { 70 | QProcess::startDetached(_command); 71 | } 72 | } 73 | } 74 | QvPlugin_EventHandler(SimpleEventHandler, SystemProxy) 75 | { 76 | /// 77 | /// Variables: 78 | /// $$HTTP: HTTP port (could be 0) 79 | /// $$SOCKS: SOCKS port (could be 0) 80 | /// 81 | const auto settings = CommandPluginConfig::fromJson(CommandPluginInstance->GetSettngs()); 82 | QStringList actions; 83 | switch (pluginEvent.systemProxyState) 84 | { 85 | case Events::SystemProxy::SetProxy: 86 | { 87 | actions << settings.setSystemProxy.split(QRegExp("[\r\n]"), SkipEmpty); 88 | break; 89 | } 90 | case Events::SystemProxy::ClearProxy: 91 | { 92 | actions << settings.clearSystemProxy.split(QRegExp("[\r\n]"), SkipEmpty); 93 | break; 94 | } 95 | } 96 | for (const auto &action : actions) 97 | { 98 | auto _command = action; 99 | _command.replace("$$HTTP", QString::number(pluginEvent.systemProxyPortSettings[Events::SystemProxy::SystemProxy_HTTP])); 100 | _command.replace("$$SOCKS", QString::number(pluginEvent.systemProxyPortSettings[Events::SystemProxy::SystemProxy_SOCKS])); 101 | bool detached = _command.contains("$$CALL"); 102 | _command.replace("$$CALL", ""); 103 | if (detached) 104 | { 105 | auto returnvalue = QProcess::execute(_command); 106 | if (returnvalue != 0) 107 | { 108 | CommandPluginInstance->PluginLog("Failed to execute command : \"" + action + "\""); 109 | } 110 | } 111 | else 112 | { 113 | QProcess::startDetached(_command); 114 | } 115 | } 116 | } 117 | QvPlugin_EventHandler(SimpleEventHandler, ConnectionEntry) 118 | { 119 | /// 120 | /// Variables: 121 | /// $$DISPLAYNAME 122 | /// $$ORIGINAL_NAME 123 | /// 124 | const auto settings = CommandPluginConfig::fromJson(CommandPluginInstance->GetSettngs()); 125 | QStringList actions; 126 | switch (pluginEvent.eventType) 127 | { 128 | case Events::ConnectionEntry::Created: 129 | { 130 | actions << settings.connectionCreated.split(QRegExp("[\r\n]"), SkipEmpty); 131 | break; 132 | } 133 | case Events::ConnectionEntry::FullyRemoved: 134 | case Events::ConnectionEntry::RemovedFromGroup: 135 | { 136 | actions << settings.connectionDeleted.split(QRegExp("[\r\n]"), SkipEmpty); 137 | break; 138 | } 139 | case Events::ConnectionEntry::Renamed: 140 | { 141 | actions << settings.connectionRenamed.split(QRegExp("[\r\n]"), SkipEmpty); 142 | break; 143 | } 144 | case Events::ConnectionEntry::Edited: 145 | { 146 | actions << settings.connectionUpdated.split(QRegExp("[\r\n]"), SkipEmpty); 147 | break; 148 | } 149 | case Events::ConnectionEntry::LinkedWithGroup: 150 | { 151 | break; 152 | } 153 | } 154 | for (const auto &action : actions) 155 | { 156 | auto _command = action; 157 | _command.replace("$$DISPLAYNAME", pluginEvent.displayName); 158 | _command.replace("$$ORIGINAL_NAME", pluginEvent.originalDisplayName); 159 | bool detached = _command.contains("$$CALL"); 160 | _command.replace("$$CALL", ""); 161 | if (detached) 162 | { 163 | auto returnvalue = QProcess::execute(_command); 164 | if (returnvalue != 0) 165 | { 166 | CommandPluginInstance->PluginLog("Failed to execute command : \"" + action + "\""); 167 | } 168 | } 169 | else 170 | { 171 | QProcess::startDetached(_command); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /core/EventHandler.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "QvPluginProcessor.hpp" 3 | 4 | class SimpleEventHandler : public Qv2rayPlugin::PluginEventHandler 5 | { 6 | public: 7 | SimpleEventHandler(); 8 | QvPlugin_EventHandler_Decl(SystemProxy); 9 | QvPlugin_EventHandler_Decl(Connectivity); 10 | QvPlugin_EventHandler_Decl(ConnectionEntry); 11 | }; 12 | -------------------------------------------------------------------------------- /resx.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | assets/qv2ray.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /ui/CommandPluginSettings.cpp: -------------------------------------------------------------------------------- 1 | #include "CommandPluginSettings.hpp" 2 | 3 | #include "CommandPlugin.hpp" 4 | #include "ui_CommandPluginSettings.h" 5 | 6 | CommandPluginSettings::CommandPluginSettings(QWidget *parent) : Qv2rayPlugin::QvPluginSettingsWidget(parent), ui(new Ui::CommandPluginSettings) 7 | { 8 | ui->setupUi(this); 9 | } 10 | 11 | void CommandPluginSettings::SetSettings(const QJsonObject &s) 12 | { 13 | this->settings.loadJson(s); 14 | ui->preConnTxt->setPlainText(settings.beforeConnection); 15 | ui->postConnTxt->setPlainText(settings.afterConnection); 16 | ui->preDisconnTxt->setPlainText(settings.beforeDisConnection); 17 | ui->postDisconnTxt->setPlainText(settings.afterDisConnection); 18 | // 19 | ui->connCreateTxt->setPlainText(settings.connectionCreated); 20 | ui->connRenameTxt->setPlainText(settings.connectionRenamed); 21 | ui->connUpdateTxt->setPlainText(settings.connectionUpdated); 22 | ui->connDeleteTxt->setPlainText(settings.connectionDeleted); 23 | // 24 | ui->setSystemProxyTxt->setPlainText(settings.setSystemProxy); 25 | ui->clearSystemProxyTxt->setPlainText(settings.clearSystemProxy); 26 | } 27 | 28 | CommandPluginSettings::~CommandPluginSettings() 29 | { 30 | delete ui; 31 | } 32 | 33 | void CommandPluginSettings::on_preConnTxt_textChanged() 34 | { 35 | settings.beforeConnection = ui->preConnTxt->toPlainText(); 36 | } 37 | 38 | void CommandPluginSettings::on_postConnTxt_textChanged() 39 | { 40 | settings.afterConnection = ui->postConnTxt->toPlainText(); 41 | } 42 | 43 | void CommandPluginSettings::on_preDisconnTxt_textChanged() 44 | { 45 | settings.beforeDisConnection = ui->preDisconnTxt->toPlainText(); 46 | } 47 | 48 | void CommandPluginSettings::on_postDisconnTxt_textChanged() 49 | { 50 | settings.afterDisConnection = ui->postDisconnTxt->toPlainText(); 51 | } 52 | 53 | void CommandPluginSettings::on_connCreateTxt_textChanged() 54 | { 55 | settings.connectionCreated = ui->connCreateTxt->toPlainText(); 56 | } 57 | 58 | void CommandPluginSettings::on_connRenameTxt_textChanged() 59 | { 60 | settings.connectionRenamed = ui->connRenameTxt->toPlainText(); 61 | } 62 | 63 | void CommandPluginSettings::on_connUpdateTxt_textChanged() 64 | { 65 | settings.connectionUpdated = ui->connUpdateTxt->toPlainText(); 66 | } 67 | 68 | void CommandPluginSettings::on_connDeleteTxt_textChanged() 69 | { 70 | settings.connectionDeleted = ui->connDeleteTxt->toPlainText(); 71 | } 72 | 73 | void CommandPluginSettings::on_setSystemProxyTxt_textChanged() 74 | { 75 | settings.setSystemProxy = ui->setSystemProxyTxt->toPlainText(); 76 | } 77 | 78 | void CommandPluginSettings::on_clearSystemProxyTxt_textChanged() 79 | { 80 | settings.clearSystemProxy = ui->clearSystemProxyTxt->toPlainText(); 81 | } 82 | -------------------------------------------------------------------------------- /ui/CommandPluginSettings.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "core/CommandConfig.hpp" 3 | #include "interface/QvGUIPluginInterface.hpp" 4 | 5 | #include 6 | 7 | namespace Ui 8 | { 9 | class CommandPluginSettings; 10 | } 11 | 12 | class CommandPluginSettings : public Qv2rayPlugin::QvPluginSettingsWidget 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit CommandPluginSettings(QWidget *parent = nullptr); 17 | ~CommandPluginSettings(); 18 | 19 | void SetSettings(const QJsonObject &s) override; 20 | 21 | QJsonObject GetSettings() override 22 | { 23 | return settings.toJson(); 24 | } 25 | 26 | private slots: 27 | void on_preConnTxt_textChanged(); 28 | void on_postConnTxt_textChanged(); 29 | void on_preDisconnTxt_textChanged(); 30 | void on_postDisconnTxt_textChanged(); 31 | void on_connCreateTxt_textChanged(); 32 | void on_connRenameTxt_textChanged(); 33 | void on_connUpdateTxt_textChanged(); 34 | void on_connDeleteTxt_textChanged(); 35 | void on_setSystemProxyTxt_textChanged(); 36 | void on_clearSystemProxyTxt_textChanged(); 37 | 38 | private: 39 | CommandPluginConfig settings; 40 | Ui::CommandPluginSettings *ui; 41 | }; 42 | -------------------------------------------------------------------------------- /ui/CommandPluginSettings.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CommandPluginSettings 4 | 5 | 6 | 7 | 0 8 | 0 9 | 729 10 | 615 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 22 | 23 | 24 | Connectivity 25 | 26 | 27 | 28 | 29 | 30 | Pre-Connection 31 | 32 | 33 | 34 | 35 | 36 | 37 | Post-Disconnection 38 | 39 | 40 | 41 | 42 | 43 | 44 | QPlainTextEdit::NoWrap 45 | 46 | 47 | 48 | 49 | 50 | 51 | QPlainTextEdit::NoWrap 52 | 53 | 54 | 55 | 56 | 57 | 58 | Post-Connecton 59 | 60 | 61 | 62 | 63 | 64 | 65 | QPlainTextEdit::NoWrap 66 | 67 | 68 | 69 | 70 | 71 | 72 | Pre-Disconnection 73 | 74 | 75 | 76 | 77 | 78 | 79 | QPlainTextEdit::NoWrap 80 | 81 | 82 | 83 | 84 | 85 | 86 | Variables: 87 | $$DISPLAYNAME 88 | $$INBOUND_inboundProtocol: port for that protocol, (e.g. $INBOUND_http as HTTP port) 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | Connection Entries 97 | 98 | 99 | 100 | 101 | 102 | QPlainTextEdit::NoWrap 103 | 104 | 105 | 106 | 107 | 108 | 109 | QPlainTextEdit::NoWrap 110 | 111 | 112 | 113 | 114 | 115 | 116 | Connection Renamed 117 | 118 | 119 | 120 | 121 | 122 | 123 | QPlainTextEdit::NoWrap 124 | 125 | 126 | 127 | 128 | 129 | 130 | Connection Updated 131 | 132 | 133 | 134 | 135 | 136 | 137 | Connection Created 138 | 139 | 140 | 141 | 142 | 143 | 144 | QPlainTextEdit::NoWrap 145 | 146 | 147 | 148 | 149 | 150 | 151 | Connection Deleted 152 | 153 | 154 | 155 | 156 | 157 | 158 | Variables: 159 | $$DISPLAYNAME 160 | $$ORIGINAL_NAME 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | System Proxy 169 | 170 | 171 | 172 | 173 | 174 | Clear System Proxy 175 | 176 | 177 | 178 | 179 | 180 | 181 | Set System Proxy 182 | 183 | 184 | 185 | 186 | 187 | 188 | Variables: 189 | $$HTTP: HTTP port (could be 0) 190 | $$SOCKS: SOCKS port (could be 0) 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | Commands start with "$$CALL" will make program start detached. 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /ui/GUIInterface.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "interface/QvGUIPluginInterface.hpp" 4 | #include "ui/CommandPluginSettings.hpp" 5 | 6 | using namespace Qv2rayPlugin; 7 | 8 | class CommandGUIInterface : public Qv2rayPlugin::PluginGUIInterface 9 | { 10 | public: 11 | QIcon Icon() const override 12 | { 13 | return QIcon(":/assets/qv2ray.png"); 14 | } 15 | 16 | QList GetComponents() const override 17 | { 18 | return { GUI_COMPONENT_SETTINGS }; 19 | } 20 | 21 | std::unique_ptr createSettingsWidgets() const override 22 | { 23 | return std::make_unique(); 24 | } 25 | 26 | QList createInboundEditors() const override 27 | { 28 | return {}; 29 | } 30 | 31 | QList createOutboundEditors() const override 32 | { 33 | return {}; 34 | } 35 | 36 | std::unique_ptr createMainWindowWidget() const override 37 | { 38 | return nullptr; 39 | } 40 | }; 41 | --------------------------------------------------------------------------------