diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bbd3fa313..a41b058aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,15 +2,14 @@ name: Build Packages on: workflow_dispatch: - -jobs: - build: - name: ${{ matrix.arch }} build - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - arch: + inputs: + arch: + description: "Select device Arch:" + required: true + default: "all" + type: choice + options: + - all - arm_cortex-a5_vfpv4 - arm_cortex-a7_neon-vfpv4 - arm_cortex-a8_vfpv3 @@ -31,6 +30,30 @@ jobs: - i386_pentium4 - x86_64 +jobs: + prebuild: + runs-on: ubuntu-latest + outputs: + arch: ${{ steps.set-matrix.outputs.arch }} + steps: + - name: Set Matrix Run + id: set-matrix + run: | + if [ "${{ inputs.arch }}" == "all" ]; then + echo "arch=['arm_cortex-a5_vfpv4','arm_cortex-a7_neon-vfpv4','arm_cortex-a8_vfpv3','arm_cortex-a9','arm_cortex-a9_vfpv3-d16','arm_cortex-a9_neon','arm_cortex-a15_neon-vfpv4','aarch64_cortex-a53','aarch64_cortex-a72','aarch64_generic','mips_24kc','mips_4kec','mips_mips32','mipsel_24kc','mipsel_24kc_24kf','mipsel_74kc','mips64_octeonplus','i386_pentium4','x86_64']" >> $GITHUB_OUTPUT + else + echo "arch=['${{ inputs.arch }}']" >> $GITHUB_OUTPUT + fi + + build: + needs: prebuild + name: ${{ matrix.arch }} build + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + arch: ${{ fromJSON(needs.prebuild.outputs.arch) }} + steps: - name: Checkout uses: actions/checkout@v4 diff --git a/luci-app-mihomo/Makefile b/luci-app-mihomo/Makefile index c6dca4cd6..ce2b2a515 100644 --- a/luci-app-mihomo/Makefile +++ b/luci-app-mihomo/Makefile @@ -1,6 +1,6 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=1.8.4 +PKG_VERSION:=1.8.5 LUCI_TITLE:=LuCI Support for mihomo LUCI_DEPENDS:=+luci-base +mihomo diff --git a/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/config.js b/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/config.js index 5a3d7abd6..36759e474 100644 --- a/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/config.js +++ b/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/config.js @@ -252,7 +252,7 @@ return view.extend({ s.tab('general', _('General Config')); - o = s.taboption('general', form.ListValue, 'log_level', _('Log Level')); + o = s.taboption('general', form.ListValue, 'log_level', '*' + ' ' + _('Log Level')); o.value('silent'); o.value('error'); o.value('warning'); @@ -269,11 +269,10 @@ return view.extend({ o.value('always', _('Enable')); o.value('off', _('Disable')); - o = s.taboption('general', widgets.NetworkSelect, 'outbound_interface', _('Outbound Interface')); + o = s.taboption('general', widgets.NetworkSelect, 'outbound_interface', '*' + ' ' + _('Outbound Interface')); o.optional = true; - o.rmempty = false; - o = s.taboption('general', form.Flag, 'ipv6', _('IPv6')); + o = s.taboption('general', form.Flag, 'ipv6', '*' + ' ' + _('IPv6')); o.rmempty = false; o = s.taboption('general', form.Value, 'tcp_keep_alive_idle', _('TCP Keep Alive Idle')); @@ -286,20 +285,20 @@ return view.extend({ s.tab('external_control', _('External Control Config')); - o = s.taboption('external_control', form.Value, 'ui_name', _('UI Name')); + o = s.taboption('external_control', form.Value, 'ui_name', '*' + ' ' + _('UI Name')); o.rmempty = false; - o = s.taboption('external_control', form.Value, 'ui_url', _('UI Url')); + o = s.taboption('external_control', form.Value, 'ui_url', '*' + ' ' + _('UI Url')); o.rmempty = false; o.value('https://mirror.ghproxy.com/https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip', 'MetaCubeXD') o.value('https://mirror.ghproxy.com/https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip', 'YACD') o.value('https://mirror.ghproxy.com/https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip', 'Razord') - o = s.taboption('external_control', form.Value, 'api_port', _('API Port')); + o = s.taboption('external_control', form.Value, 'api_port', '*' + ' ' + _('API Port')); o.datatype = 'port'; o.placeholder = '9090'; - o = s.taboption('external_control', form.Value, 'api_secret', _('API Secret')); + o = s.taboption('external_control', form.Value, 'api_secret', '*' + ' ' + _('API Secret')); o.rmempty = false; o = s.taboption('external_control', form.Flag, 'selection_cache', _('Save Proxy Selection')); @@ -307,30 +306,30 @@ return view.extend({ s.tab('inbound', _('Inbound Config')); - o = s.taboption('inbound', form.Flag, 'allow_lan', _('Allow Lan')); + o = s.taboption('inbound', form.Flag, 'allow_lan', '*' + ' ' + _('Allow Lan')); o.rmempty = false; - o = s.taboption('inbound', form.Value, 'http_port', _('HTTP Port')); + o = s.taboption('inbound', form.Value, 'http_port', '*' + ' ' + _('HTTP Port')); o.datatype = 'port'; o.placeholder = '8080'; - o = s.taboption('inbound', form.Value, 'socks_port', _('SOCKS Port')); + o = s.taboption('inbound', form.Value, 'socks_port', '*' + ' ' + _('SOCKS Port')); o.datatype = 'port'; o.placeholder = '1080'; - o = s.taboption('inbound', form.Value, 'mixed_port', _('Mixed Port')); + o = s.taboption('inbound', form.Value, 'mixed_port', '*' + ' ' + _('Mixed Port')); o.datatype = 'port'; o.placeholder = '7890'; - o = s.taboption('inbound', form.Value, 'redir_port', _('Redirect Port')); + o = s.taboption('inbound', form.Value, 'redir_port', '*' + ' ' + _('Redirect Port')); o.datatype = 'port'; o.placeholder = '7891'; - o = s.taboption('inbound', form.Value, 'tproxy_port', _('TPROXY Port')); + o = s.taboption('inbound', form.Value, 'tproxy_port', '*' + ' ' + _('TPROXY Port')); o.datatype = 'port'; o.placeholder = '7892'; - o = s.taboption('inbound', form.Flag, 'authentication', _('Authentication')); + o = s.taboption('inbound', form.Flag, 'authentication', '*' + ' ' + _('Overwrite Authentication')); o.rmempty = false; o = s.taboption('inbound', form.SectionValue, '_authentications', form.TableSection, 'authentication', _('Edit Authentications')); @@ -351,27 +350,27 @@ return view.extend({ s.tab('tun', _('TUN Config')); - o = s.taboption('tun', form.ListValue, 'tun_stack', _('Stack')); + o = s.taboption('tun', form.ListValue, 'tun_stack', '*' + ' ' + _('Stack')); o.value('system', 'System'); o.value('gvisor', 'gVisor'); o.value('mixed', 'Mixed'); - o = s.taboption('tun', form.Value, 'tun_mtu', _('MTU')); + o = s.taboption('tun', form.Value, 'tun_mtu', '*' + ' ' + _('MTU')); o.placeholder = '9000'; - o = s.taboption('tun', form.Flag, 'tun_gso', _('GSO')); + o = s.taboption('tun', form.Flag, 'tun_gso', '*' + ' ' + _('GSO')); o.rmempty = false; - o = s.taboption('tun', form.Value, 'tun_gso_max_size', _('GSO Max Size')); + o = s.taboption('tun', form.Value, 'tun_gso_max_size', '*' + ' ' + _('GSO Max Size')); o.placeholder = '65536'; o.depends('tun_gso', '1'); - o = s.taboption('tun', form.Flag, 'tun_endpoint_independent_nat', _('Endpoint Independent NAT')); + o = s.taboption('tun', form.Flag, 'tun_endpoint_independent_nat', '*' + ' ' + _('Endpoint Independent NAT')); o.rmempty = false; s.tab('dns', _('DNS Config')); - o = s.taboption('dns', form.Value, 'dns_port', _('DNS Port')); + o = s.taboption('dns', form.Value, 'dns_port', '*' + ' ' + _('DNS Port')); o.datatype = 'port'; o.placeholder = '1053'; diff --git a/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/editor.js b/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/editor.js index f5ac8c47b..01f863ee4 100644 --- a/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/editor.js +++ b/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/editor.js @@ -7,52 +7,88 @@ return view.extend({ load: function () { - return Promise.all([ - uci.load('mihomo'), - mihomo.listProfiles(), - ]); + return fs.stat('/www/tinyfilemanager').then(function (stat) { + if (stat.type === 'directory') { + return '/tinyfilemanager/index.php?p=etc%2Fmihomo%2Frun'; + } else { + throw new Error('Directory TinyFile Manager not found'); + } + }).catch(function () { + return fs.stat('/www/tinyfm').then(function (stat) { + if (stat.type === 'directory') { + return '/tinyfm/tinyfm.php?p=etc%2Fmihomo%2Frun'; + } else { + throw new Error('Directory TinyFile Manager not found'); + } + }).catch(function () { + return null; + }); + }); }, - render: function (data) { - const profiles = data[1]; + render: function (iframePath) { + if (iframePath) { + const host = window.location.hostname; + const iframeUrl = `http://${host}${iframePath}`; + + m = new form.Map('mihomo', _('MiHomo Config Editor')); - let m, s, o; - - m = new form.Map('mihomo'); + let container = E('div', { class: 'cbi-section' }, [ + E('iframe', { + src: iframeUrl, + width: '100%', + height: '600px', + frameborder: '0' + }, _('Your browser does not support iframes.')) + ]); - s = m.section(form.NamedSection, 'editor', 'editor'); + return container; + } else { + let m, s, o; - o = s.option(form.ListValue, '_profile', _('Choose Profile')); - o.optional = true; + m = new form.Map('mihomo', _('MiHomo Profile Editor')); - for (const profile of profiles) { - o.value(mihomo.profilesDir + '/' + profile.name, _('File:') + profile.name); - } - o.value(mihomo.mixinFilePath, _('File for Mixin')); - o.value(mihomo.runProfilePath, _('Profile for Startup')); - o.value(mihomo.reservedIPNFT, _('File for Reserved IP')); - o.value(mihomo.reservedIP6NFT, _('File for Reserved IP6')); - - o.write = function (section_id, formvalue) { - return true; - }; - o.onchange = function (event, section_id, value) { - return L.resolveDefault(fs.read_direct(value), '').then(function (content) { - m.lookupOption('mihomo.editor._profile_content')[0].getUIElement('editor').setValue(content); + s = m.section(form.NamedSection, 'editor', 'editor', _('Edit MiHomo profiles')); + + o = s.option(form.ListValue, '_profile', _('Choose Profile')); + o.optional = true; + + return Promise.all([ + uci.load('mihomo'), + mihomo.listProfiles(), + ]).then(function (data) { + const profiles = data[1]; + + for (const profile of profiles) { + o.value(mihomo.profilesDir + '/' + profile.name, _('File:') + profile.name); + } + o.value(mihomo.mixinFilePath, _('File for Mixin')); + o.value(mihomo.runProfilePath, _('Profile for Startup')); + o.value(mihomo.reservedIPNFT, _('File for Reserved IP')); + o.value(mihomo.reservedIP6NFT, _('File for Reserved IP6')); + + o.write = function (section_id, formvalue) { + return true; + }; + o.onchange = function (event, section_id, value) { + return L.resolveDefault(fs.read_direct(value), '').then(function (content) { + m.lookupOption('mihomo.editor._profile_content')[0].getUIElement('editor').setValue(content); + }); + }; + + o = s.option(form.TextValue, '_profile_content'); + o.rows = 25; + o.write = function (section_id, formvalue) { + const path = m.lookupOption('mihomo.editor._profile')[0].formvalue('editor'); + return fs.write(path, formvalue); + }; + o.remove = function (section_id) { + const path = m.lookupOption('mihomo.editor._profile')[0].formvalue('editor'); + return fs.write(path); + }; + + return m.render(); }); - }; - - o = s.option(form.TextValue, '_profile_content',); - o.rows = 25; - o.write = function (section_id, formvalue) { - const path = m.lookupOption('mihomo.editor._profile')[0].formvalue('editor'); - return fs.write(path, formvalue); - }; - o.remove = function (section_id) { - const path = m.lookupOption('mihomo.editor._profile')[0].formvalue('editor'); - return fs.write(path); - }; - - return m.render(); + } }, handleSaveApply: function (ev, mode) { return this.handleSave(ev).finally(function() { diff --git a/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/editortinyfm.js b/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/editortinyfm.js deleted file mode 100644 index 8b492b7d2..000000000 --- a/luci-app-mihomo/htdocs/luci-static/resources/view/mihomo/editortinyfm.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; -'require view'; -'require fs'; - -return view.extend({ - load: function () { - // Check if the first directory exists - return fs.stat('/www/tinyfilemanager').then(function (stat) { - if (stat.type === 'directory') { - // If the directory exists, return the URL for tinyfilemanager - return '/tinyfilemanager/index.php?p=etc%2Fmihomo%2Frun'; - } else { - throw new Error('Directory not found'); - } - }).catch(function () { - // If tinyfilemanager is not found, check for tinyfm - return fs.stat('/www/tinyfm').then(function (stat) { - if (stat.type === 'directory') { - return '/tinyfm/tinyfm.php?p=etc%2Fmihomo%2Frun'; - } else { - throw new Error('Directory not found'); - } - }).catch(function () { - // If neither directory is found, fallback to a not found page - return '/notfound'; // Optional fallback URL - }); - }); - }, - render: function (iframePath) { - // Dynamically get the current host or IP address of the OpenWrt router - const host = window.location.hostname; - const iframeUrl = `http://${host}${iframePath}`; - - // Create a div container for the iframe - let container = E('div', { class: 'cbi-section' }, [ - E('iframe', { - src: iframeUrl, - width: '100%', - height: '600px', - frameborder: '0' - }, _('Your browser does not support iframes.')) - ]); - - // Return the container for rendering - return container; - } -}); diff --git a/luci-app-mihomo/po/zh_Hans/mihomo.po b/luci-app-mihomo/po/zh_Hans/mihomo.po index 94b27ca02..9368fba44 100644 --- a/luci-app-mihomo/po/zh_Hans/mihomo.po +++ b/luci-app-mihomo/po/zh_Hans/mihomo.po @@ -244,8 +244,8 @@ msgstr "Redirect 端口" msgid "TPROXY Port" msgstr "TPROXY 端口" -msgid "Authentication" -msgid "身份验证" +msgid "Overwrite Authentication" +msgstr "覆盖身份验证" msgid "Edit Authentications" msgstr "编辑身份验证" diff --git a/luci-app-mihomo/root/usr/share/luci/menu.d/luci-app-mihomo.json b/luci-app-mihomo/root/usr/share/luci/menu.d/luci-app-mihomo.json index 7f2e723ba..12728e5ee 100644 --- a/luci-app-mihomo/root/usr/share/luci/menu.d/luci-app-mihomo.json +++ b/luci-app-mihomo/root/usr/share/luci/menu.d/luci-app-mihomo.json @@ -26,17 +26,9 @@ "path": "mihomo/editor" } }, - "admin/services/mihomo/editortinyfm": { - "title": "Editor TinyFM", - "order": 30, - "action": { - "type": "view", - "path": "mihomo/editortinyfm" - } - }, "admin/services/mihomo/log": { "title": "Log", - "order": 40, + "order": 30, "action": { "type": "view", "path": "mihomo/log" diff --git a/mihomo/files/mihomo.init b/mihomo/files/mihomo.init index 59b3d62a9..2aa23de73 100644 --- a/mihomo/files/mihomo.init +++ b/mihomo/files/mihomo.init @@ -146,13 +146,13 @@ start_service() { # do mixin log_level="$log_level" ipv6="$ipv6" \ ui_path="ui" ui_name="$ui_name" ui_url="$ui_url" api_listen="0.0.0.0:$api_port" api_secret="$api_secret" \ - http_port="$http_port" socks_port="$socks_port" mixed_port="$mixed_port" redir_port="$redir_port" tproxy_port="$tproxy_port" \ + allow_lan="$allow_lan" http_port="$http_port" socks_port="$socks_port" mixed_port="$mixed_port" redir_port="$redir_port" tproxy_port="$tproxy_port" \ tun_enable="$tun_enable" tun_stack="$tun_stack" tun_device="$TUN_DEVICE" tun_mtu="$tun_mtu" tun_gso="$tun_gso" tun_gso_max_size="$tun_gso_max_size" tun_endpoint_independent_nat="$tun_endpoint_independent_nat" \ dns_enable="true" dns_listen="0.0.0.0:$dns_port" \ yq -M -i ' .log-level = env(log_level) | .ipv6 = env(ipv6) == 1 | .external-ui = env(ui_path) | .external-ui-name = env(ui_name) | .external-ui-url = env(ui_url) | .external-controller = env(api_listen) | .secret = env(api_secret) | - .port = env(http_port) | .socks-port = env(socks_port) | .mixed-port = env(mixed_port) | .redir-port = env(redir_port) | .tproxy-port = env(tproxy_port) | + .allow-lan = env(allow_lan) == 1 | .port = env(http_port) | .socks-port = env(socks_port) | .mixed-port = env(mixed_port) | .redir-port = env(redir_port) | .tproxy-port = env(tproxy_port) | .tun.enable = env(tun_enable) == 1 | .tun.stack = env(tun_stack) | .tun.device = env(tun_device) | .tun.mtu = env(tun_mtu) | .tun.gso = env(tun_gso) == 1 | .tun.gso-max-size = env(tun_gso_max_size) | .tun.endpoint-independent-nat = env(tun_endpoint_independent_nat) == 1 | .dns.enable = env(dns_enable) | .dns.listen = env(dns_listen) ' "$RUN_PROFILE_PATH" @@ -178,10 +178,6 @@ start_service() { .geo-auto-update = env(geox_auto_update) == 1 | .geo-update-interval = env(geox_update_interval) ' "$RUN_PROFILE_PATH" - if [ "$authentication" == 1 ]; then - yq -M -i 'del(.authentication)' "$RUN_PROFILE_PATH" - config_foreach mixin_authentications "authentication" - fi if [ "$fake_ip_filter" == 1 ]; then fake_ip_filter_mode="$fake_ip_filter_mode" \ yq -M -i 'del(.dns.fake-ip-filter) | .dns.fake-ip-filter-mode = env(fake_ip_filter_mode)' "$RUN_PROFILE_PATH" @@ -205,9 +201,6 @@ start_service() { fi fi yq -M -i 'del (.bind-address)' "$RUN_PROFILE_PATH" - if [ "$tun_enable" == 1 ]; then - yq -M -i '.tun.auto-route = false | .tun.auto-redirect = false | .tun.auto-detect-interface = false | .tun.dns-hijack = []' "$RUN_PROFILE_PATH" - fi if [ -n "$outbound_interface" ]; then local outbound_device network_get_device outbound_device "$outbound_interface" @@ -215,6 +208,13 @@ start_service() { outbound_device="$outbound_device" yq -M -i '.interface-name = env(outbound_device)' "$RUN_PROFILE_PATH" fi fi + if [ "$authentication" == 1 ]; then + yq -M -i 'del(.authentication)' "$RUN_PROFILE_PATH" + config_foreach mixin_authentications "authentication" + fi + if [ "$tun_enable" == 1 ]; then + yq -M -i '.tun.auto-route = false | .tun.auto-redirect = false | .tun.auto-detect-interface = false | .tun.dns-hijack = []' "$RUN_PROFILE_PATH" + fi # test profile if [ "$test_profile" == 1 ]; then log "Profile testing..."