mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-10 18:34:18 +08:00
🗽 Sync 2026-08-04 20:40:02
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=airconnect
|
||||
PKG_VERSION:=1.10.1
|
||||
PKG_VERSION:=1.11.1
|
||||
PKG_RELEASE=1
|
||||
|
||||
PKG_SOURCE:=AirConnect-$(PKG_VERSION).zip
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=daed
|
||||
PKG_VERSION:=2026.08.03
|
||||
PKG_RELEASE:=40
|
||||
PKG_RELEASE:=41
|
||||
|
||||
PKG_SOURCE:=daed-src-2026.08.03-5f7939adc12a.tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
diff --git a/graphql/service/subscription/mutation_utils.go b/graphql/service/subscription/mutation_utils.go
|
||||
index e01a342..c6bc3e1 100644
|
||||
--- a/graphql/service/subscription/mutation_utils.go
|
||||
+++ b/graphql/service/subscription/mutation_utils.go
|
||||
@@ -171,6 +171,8 @@ func AutoUpdateVersionByIds(d *gorm.DB, ids []uint) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
+const scheduledUpdateTimeout = 3 * time.Minute
|
||||
+
|
||||
var (
|
||||
schedulerCache = make(map[uint]*gocron.Scheduler)
|
||||
schedulerMu sync.RWMutex
|
||||
@@ -224,7 +226,9 @@ func AddUpdateScheduler(ctx context.Context, id uint) {
|
||||
}
|
||||
logrus.Info("Subscription " + tag + " update task enabled, with exp " + sub.CronExp)
|
||||
_, err := s.Cron(sub.CronExp).Do(func() {
|
||||
- if _, err := UpdateById(context.Background(), sub.ID); err != nil {
|
||||
+ ctx, cancel := context.WithTimeout(context.Background(), scheduledUpdateTimeout)
|
||||
+ defer cancel()
|
||||
+ if _, err := UpdateById(ctx, sub.ID); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
})
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.0-r20250610
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.0-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for arcadia
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -24,7 +24,7 @@ s = m:section(TypedSection, "arcadia", translate("Setup"),
|
||||
s.addremove=false
|
||||
s.anonymous=true
|
||||
|
||||
o = s:option(Value, "image", translate("Image"))
|
||||
o = s:option(Value, "image", translate("Docker Image"))
|
||||
o.datatype = "string"
|
||||
o:value("", translate("Default"))
|
||||
o:value("supermanito/arcadia:beta", "supermanito/arcadia:beta")
|
||||
|
||||
@@ -16,7 +16,7 @@ msgstr "项目基于 TypeScript 全栈开发,采用了众多前沿技术,前
|
||||
msgid "The initial username and password are 'useradmin' and 'passwd' respectively."
|
||||
msgstr "初始的用户名和密码分别是'useradmin'和'passwd'。"
|
||||
|
||||
msgid "Image"
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Default"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.3-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.3-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for ChineseSubFinder
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -28,7 +28,7 @@ o.rmempty = false
|
||||
o.default = "19037"
|
||||
o.datatype = "string"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("allanpk716/chinesesubfinder:latest-lite", "allanpk716/chinesesubfinder:latest-lite")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "ChineseSubFinder是一个自动化中文字幕下载工具。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "HTTP Port"
|
||||
msgstr "HTTP 端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.2-r20251011
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for CodeServer
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -22,7 +22,7 @@ o = s:option(Value, "http_port", translate("HTTP Port").."<b>*</b>")
|
||||
o.default = "8085"
|
||||
o.datatype = "string"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("lscr.io/linuxserver/code-server:latest", "lscr.io/linuxserver/code-server:latest")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "CodeServer 就一个在线版本的 VSCode,可以在线开发。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "HTTP Port"
|
||||
msgstr "HTTP 端口"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ LUCI_TITLE:=LuCI support for Timewol
|
||||
LUCI_DEPENDS:=+etherwake
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=1.1
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
[ ! -f "/usr/share/ucitrack/luci-app-luci_app_control_timewol.json" ] && {
|
||||
cat > /usr/share/ucitrack/luci-app-luci_app_control_timewol.json << EEOF
|
||||
{
|
||||
"config": "luci_app_control_timewol",
|
||||
"init": "luci_app_control_timewol"
|
||||
}
|
||||
EEOF
|
||||
}
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@luci_app_control_timewol[-1]
|
||||
add ucitrack luci_app_control_timewol
|
||||
set ucitrack.@luci_app_control_timewol[-1].init=luci-app-control-timewol
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -rf /tmp/luci-*cache
|
||||
exit 0
|
||||
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=LuCI support for Webrestriction
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=1.1
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
[ ! -f "/usr/share/ucitrack/luci-app-luci_app_control_webrestriction.json" ] && {
|
||||
cat > /usr/share/ucitrack/luci-app-luci_app_control_webrestriction.json << EEOF
|
||||
{
|
||||
"config": "luci_app_control_webrestriction",
|
||||
"init": "luci_app_control_webrestriction"
|
||||
}
|
||||
EEOF
|
||||
}
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@luci_app_control_webrestriction[-1]
|
||||
add ucitrack luci_app_control_webrestriction
|
||||
set ucitrack.@luci_app_control_webrestriction[-1].init=luci-app-control-webrestriction
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -rf /tmp/luci-*cache
|
||||
exit 0
|
||||
@@ -9,7 +9,7 @@ LUCI_TITLE:=LuCI support for Weburl
|
||||
LUCI_DEPENDS:=+iptables-mod-filter +kmod-ipt-filter
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=1.1
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
[ ! -f "/usr/share/ucitrack/luci-app-luci_app_control_weburl.json" ] && {
|
||||
cat > /usr/share/ucitrack/luci-app-luci_app_control_weburl.json << EEOF
|
||||
{
|
||||
"config": "luci_app_control_weburl",
|
||||
"init": "luci_app_control_weburl"
|
||||
}
|
||||
EEOF
|
||||
}
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@luci_app_control_weburl[-1]
|
||||
add ucitrack luci_app_control_weburl
|
||||
set ucitrack.@luci_app_control_weburl[-1].init=luci-app-control-weburl
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -rf /tmp/luci-*cache
|
||||
exit 0
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.2.0-r20250625
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.2.0-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for demon
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -21,7 +21,7 @@ o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||
o.default = "18888"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("images-cluster.xycloud.com/wxedge/amd64-wxedge:3.5.1-CTWXKS1748570956", "images-cluster.xycloud.com/wxedge/amd64-wxedge:3.5.1-CTWXKS1748570956")
|
||||
|
||||
@@ -7,6 +7,9 @@ msgstr "容器魔王"
|
||||
msgid "Cache path"
|
||||
msgstr "缓存文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Service Status"
|
||||
msgstr "服务状态"
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
# Updated: 2025-10-09
|
||||
PKG_VERSION:=1.0.0-r20251009
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.0-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for DPanel
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -35,7 +35,7 @@ o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||
o.default = "8807"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("dpanel/dpanel:lite", "dpanel/dpanel:lite")
|
||||
|
||||
@@ -10,7 +10,7 @@ msgstr "DPanel — 轻量级仪表盘服务。"
|
||||
msgid "DPanel"
|
||||
msgstr "DPanel"
|
||||
|
||||
msgid "Image"
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Config path"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.3-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.3-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for Emby
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -27,7 +27,7 @@ o.default = "8097"
|
||||
o.datatype = "port"
|
||||
o:depends("hostnet", 0)
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("emby/embyserver", "emby/embyserver")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "Emby 是一个多媒体串流平台。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "HTTP Port"
|
||||
msgstr "HTTP 端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.0-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.0-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for Excalidraw
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -35,7 +35,7 @@ o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||
o.default = "8090"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_ver", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_ver", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o.default = "v0.13.0"
|
||||
|
||||
@@ -13,6 +13,9 @@ msgstr "Excalidraw 是支持多人协同的私有化在线画板工具。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ PKG_NAME:=luci-app-fchomo
|
||||
define Package/luci-app-fchomo/conffiles
|
||||
/etc/config/fchomo
|
||||
/etc/fchomo/certs/
|
||||
/etc/fchomo/node/
|
||||
/etc/fchomo/provider/
|
||||
/etc/fchomo/ruleset/
|
||||
/etc/fchomo/resources/
|
||||
|
||||
@@ -204,7 +204,9 @@ const outbound_type = [
|
||||
['hysteria2', _('Hysteria2') + ' - ' + _('UDP')],
|
||||
['shadowquic', _('ShadowQUIC') + ' - ' + _('UDP')],
|
||||
['trusttunnel', _('TrustTunnel') + ' - ' + _('TCP/UDP')],
|
||||
['zerotier', _('ZeroTier') + ' - ' + _('UDP') + ' - ' + _('L2')], // Endpoint
|
||||
['wireguard', _('WireGuard') + ' - ' + _('UDP')], // Endpoint
|
||||
['tailscale', _('Tailscale') + ' - ' + _('UDP')], // Endpoint
|
||||
['masque', _('Masque') + ' - ' + _('UDP')], // Endpoint // https://blog.cloudflare.com/post-quantum-warp/
|
||||
['ssh', _('SSH') + ' - ' + _('TCP')]
|
||||
];
|
||||
@@ -1879,6 +1881,18 @@ function validateUrl(section_id, value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateHexstr(length, section_id, value) {
|
||||
if (!value)
|
||||
return true;
|
||||
|
||||
length /= 4; // Convert bits to hex characters
|
||||
const regexp = new RegExp(`^[0-9a-fA-F]{${length}}$`);
|
||||
if (!value.match(regexp))
|
||||
return _('Expecting: %s').format(_('valid hex string with %d characters').format(length));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateBase64Key(length, section_id, value) {
|
||||
/* Thanks to luci-proto-wireguard */
|
||||
if (value)
|
||||
@@ -1986,15 +2000,15 @@ function lsDir(type) {
|
||||
});
|
||||
}
|
||||
|
||||
function readFile(type, filename) {
|
||||
function readFile(type, filename, isbinary) {
|
||||
const callReadFile = rpc.declare({
|
||||
object: 'luci.fchomo',
|
||||
method: 'file_read',
|
||||
params: ['type', 'filename'],
|
||||
params: ['type', 'filename', 'isbinary'],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
return L.resolveDefault(callReadFile(type, filename), {}).then((res) => {
|
||||
return L.resolveDefault(callReadFile(type, filename, isbinary), {}).then((res) => {
|
||||
if (res.content ?? true) {
|
||||
return res.content;
|
||||
} else
|
||||
@@ -2002,15 +2016,15 @@ function readFile(type, filename) {
|
||||
});
|
||||
}
|
||||
|
||||
function writeFile(type, filename, content) {
|
||||
function writeFile(type, filename, content, isbinary) {
|
||||
const callWriteFile = rpc.declare({
|
||||
object: 'luci.fchomo',
|
||||
method: 'file_write',
|
||||
params: ['type', 'filename', 'content'],
|
||||
params: ['type', 'filename', 'content', 'isbinary'],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
return L.resolveDefault(callWriteFile(type, filename, content), {}).then((res) => {
|
||||
return L.resolveDefault(callWriteFile(type, filename, content, isbinary), {}).then((res) => {
|
||||
if (res.result) {
|
||||
return res.result;
|
||||
} else
|
||||
@@ -2182,6 +2196,7 @@ return baseclass.extend({
|
||||
validateUUID,
|
||||
validateUrl,
|
||||
// validate with bind this
|
||||
validateHexstr,
|
||||
validateBase64Key,
|
||||
validateMTLSClientAuth,
|
||||
validatePresetIDs,
|
||||
|
||||
@@ -232,6 +232,19 @@ return view.extend({
|
||||
ss.hm_prefmt = hm.glossary[ss.sectiontype].prefmt;
|
||||
ss.hm_field = hm.glossary[ss.sectiontype].field;
|
||||
ss.hm_lowcase_only = true;
|
||||
/* Remove idle files start */
|
||||
ss.renderSectionAdd = function(/* ... */) {
|
||||
let el = hm.GridSection.prototype.renderSectionAdd.apply(this, arguments);
|
||||
|
||||
el.appendChild(E('button', {
|
||||
'class': 'cbi-button cbi-button-add',
|
||||
'title': _('Remove idles'),
|
||||
'click': ui.createHandlerFn(this, hm.handleRemoveIdles)
|
||||
}, [ _('Remove idles') ]));
|
||||
|
||||
return el;
|
||||
}
|
||||
/* Remove idle files end */
|
||||
|
||||
ss.tab('field_general', _('General fields'));
|
||||
ss.tab('field_plugin', _('Plugin fields'));
|
||||
@@ -261,12 +274,12 @@ return view.extend({
|
||||
so = ss.taboption('field_general', form.Value, 'server', _('Server address'));
|
||||
so.datatype = 'host';
|
||||
so.rmempty = false;
|
||||
so.depends({type: /^(rematch|direct)$/, '!reverse': true});
|
||||
so.depends({type: /^(rematch|direct|zerotier|tailscale)$/, '!reverse': true});
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'port', _('Port'));
|
||||
so.datatype = 'port';
|
||||
so.rmempty = false;
|
||||
so.depends({type: /^(rematch|direct|mieru)$/, '!reverse': true});
|
||||
so.depends({type: /^(rematch|direct|mieru|zerotier|tailscale)$/, '!reverse': true});
|
||||
|
||||
/* Rematch fields */
|
||||
// https://github.com/MetaCubeX/mihomo/pull/2862
|
||||
@@ -782,15 +795,131 @@ return view.extend({
|
||||
so.depends('type', 'trusttunnel');
|
||||
so.modalonly = true;
|
||||
|
||||
/* ZeroTier fields */
|
||||
so = ss.taboption('field_general', form.Value, 'zerotier_network_id', 'Network ID');
|
||||
so.placeholder = '0123456789abcdef';
|
||||
so.validate = L.bind(hm.validateHexstr, so, 64);
|
||||
so.rmempty = false;
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'zerotier_trace_target', _('Remote trace target'),
|
||||
_('%s of the %s used to receiving remote debugging log.').format('Node ID', 'Node'));
|
||||
so.placeholder = '0123456789';
|
||||
so.validate = L.bind(hm.validateHexstr, so, 40);
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'zerotier_trace_level', _('Remote trace level'));
|
||||
so.value('0', _('Normal'));
|
||||
so.value('10', _('Verbose'));
|
||||
so.value('15', _('Rules'));
|
||||
so.value('20', _('Debug'));
|
||||
so.value('30', _('Insane'));
|
||||
so.depends({zerotier_trace_target: /.+/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'zerotier_physical_mtu', _('Physical MTU'),
|
||||
_('ZeroTier UDP payload MTU.'));
|
||||
so.datatype = 'range(510, 10324)';
|
||||
so.placeholder = '1432';
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'zerotier_low_bandwidth', _('Low Bandwidth Mode'),
|
||||
_('Reduces background traffic and network configuration refresh frequency.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'zerotier_encrypted_hello', _('Encrypted Hello'),
|
||||
_('Use protocol-13 extended encryption for outgoing HELLO packets.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.RichListValue, 'zerotier_fallback_mode', _('Fallback mode'));
|
||||
so.value('auto', _('Auto'), _('Uses relay after UDP direct failure.'));
|
||||
so.value('force', _('Force'), _('Uses TCP relay only.'));
|
||||
so.value('disable', _('Disable'), _('Turns TCP relay off.'));
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'zerotier_fallback_relay', _('Fallback relay'));
|
||||
so.datatype = 'hostport';
|
||||
so.placeholder = '204.80.128.1:443';
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.TextValue, 'zerotier_planet_file', 'Planet file',
|
||||
_('Used to replace the built-in official %s.').format('<code>Earth</code> Planet file'));
|
||||
so.placeholder = _('Add the base64 text of the planet file here.');
|
||||
so.load = function(section_id) {
|
||||
const vaule = form.TextValue.prototype.load.apply(this, arguments);
|
||||
|
||||
if (vaule)
|
||||
return L.resolveDefault(hm.readFile(this.section.sectiontype, section_id + '/planet', '1'), '');
|
||||
else
|
||||
return vaule;
|
||||
}
|
||||
so.write = function(section_id, formvalue) {
|
||||
form.TextValue.prototype.write.call(this, section_id, '1');
|
||||
|
||||
return hm.writeFile.call(this, this.section.sectiontype, section_id + '/planet', formvalue, '1');
|
||||
}
|
||||
so.remove = function(section_id) {
|
||||
form.TextValue.prototype.remove.apply(this, arguments);
|
||||
|
||||
return hm.removeFile.call(this, this.section.sectiontype, section_id + '/planet');
|
||||
}
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.DynamicList, 'zerotier_orbit', 'Orbit',
|
||||
_('Join %s. Format: <code>%s</code>').format('Moons', '000000<10-digit Moon World ID>:<10-digit Node ID of one Moon Root server>...'));
|
||||
so.placeholder = '000000deadbeef00:deadbeef00:deadbeef11';
|
||||
so.validate = function(section_id, value) {
|
||||
if (!value)
|
||||
return true;
|
||||
|
||||
if (!/^[0-9a-fA-F]{16}(:[0-9a-fA-F]{10})+$/.test(value))
|
||||
return _('Expecting: %s').format(_('Valid 16-digit Moon World ID and 10-digit Node ID of Moon Root server.'));
|
||||
|
||||
return true;
|
||||
}
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'zerotier_ipstack', _('IP stack'));
|
||||
so.value('', _('Keep default'));
|
||||
so.value('auto', _('Auto'));
|
||||
so.value('gvisor', _('gVisor'));
|
||||
so.value('mips', _('mihomo IP stack (MIPS)'));
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
/* WireGuard fields */
|
||||
so = ss.taboption('field_general', form.Value, 'wireguard_private_key', _('Private key'),
|
||||
so = ss.taboption('field_general', hm.GenValue, 'wireguard_private_key', _('Private key'),
|
||||
_('WireGuard requires base64-encoded private keys.'));
|
||||
so.hm_options = {
|
||||
type: 'wg-keypair',
|
||||
callback: function(result) {
|
||||
return [
|
||||
[this.option, result.private_key],
|
||||
['wireguard_public_key', result.public_key]
|
||||
]
|
||||
}
|
||||
}
|
||||
so.password = true;
|
||||
so.validate = L.bind(hm.validateBase64Key, so, 44);
|
||||
so.rmempty = false;
|
||||
so.depends('type', 'wireguard');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', hm.CopyValue, 'wireguard_public_key', _('Public key'));
|
||||
so.depends('type', 'wireguard');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'wireguard_peer_public_key', _('Peer public key'),
|
||||
_('WireGuard peer public key.'));
|
||||
so.validate = L.bind(hm.validateBase64Key, so, 44);
|
||||
@@ -823,6 +952,45 @@ return view.extend({
|
||||
so.depends('type', 'wireguard');
|
||||
so.modalonly = true;
|
||||
|
||||
/* Tailscale fields */
|
||||
so = ss.taboption('field_general', form.Value, 'tailscale_hostname', _('%s Hostname').format(_('Tailscale')));
|
||||
so.datatype = 'hostname';
|
||||
so.depends('type', 'tailscale');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'tailscale_control_url', _('Control server'),
|
||||
_('Custom %s control server.').format(_('Headscale/Tailscale')));
|
||||
so.validate = hm.validateUrl;
|
||||
so.depends('type', 'tailscale');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'tailscale_auth_key', _('Authentication key'));
|
||||
so.password = true;
|
||||
so.depends('type', 'tailscale');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'tailscale_ephemeral', _('As ephemeral node'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'tailscale');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'tailscale_accept_routes', _('Accept routes'),
|
||||
_('Whether to accept routes advertised by other nodes.'));
|
||||
so.default = so.disabled;
|
||||
so.depends('type', 'tailscale');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'tailscale_exit_node', _('Exit node'));
|
||||
so.datatype = "or(ipaddr(1), 'auto:any')";
|
||||
so.depends('type', 'tailscale');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'tailscale_exit_node_allow_lan_access', _('Allow LAN access'),
|
||||
_('Allow access to the local LAN via the exit node.'));
|
||||
so.default = so.disabled;
|
||||
so.depends({tailscale_exit_node: /.+/});
|
||||
so.modalonly = true;
|
||||
|
||||
/* Masque fields */
|
||||
so = ss.taboption('field_general', form.Value, 'masque_private_key', _('Private key'),
|
||||
_('Base64 encoded ECDSA private key on the NIST P-256 curve.'));
|
||||
@@ -832,7 +1000,7 @@ return view.extend({
|
||||
so.depends('type', 'masque');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.Value, 'masque_endpoint_public_key', _('Endpoint public key'),
|
||||
so = ss.taboption('field_general', form.Value, 'masque_endpoint_public_key', _('Server public key'),
|
||||
_('Base64 encoded ECDSA public key on the NIST P-256 curve.'));
|
||||
so.validate = L.bind(hm.validateBase64Key, so, 124);
|
||||
so.rmempty = false;
|
||||
@@ -887,6 +1055,7 @@ return view.extend({
|
||||
})
|
||||
so.depends({type: /^(tuic|shadowquic|trusttunnel)$/});
|
||||
so.depends({type: 'masque', masque_network: /^(|h3-l4proxy)$/});
|
||||
so.depends({type: 'zerotier', zerotier_ipstack: /^(auto|mips)$/}); // not empty not gvisor
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_general', form.ListValue, 'bbr_profile', _('BBR profile'));
|
||||
@@ -914,7 +1083,7 @@ return view.extend({
|
||||
|
||||
so = ss.taboption('field_general', form.Flag, 'udp', _('UDP'));
|
||||
so.default = so.disabled;
|
||||
so.depends({type: /^(rematch|direct|socks5|ss|mieru|vmess|vless|trojan|anytls|trusttunnel|wireguard|masque)$/});
|
||||
so.depends({type: /^(rematch|direct|socks5|ss|mieru|vmess|vless|trojan|anytls|trusttunnel|zerotier|wireguard|tailscale|masque)$/});
|
||||
so.depends({type: 'snell', snell_version: /^(3|4|5)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
@@ -1124,7 +1293,7 @@ return view.extend({
|
||||
so.default = so.disabled;
|
||||
so.validate = function(section_id, value) {
|
||||
const type = this.section.getOption('type').formvalue(section_id);
|
||||
let tls = this.section.getUIElement(section_id, 'tls').node.querySelector('input');
|
||||
const tls = this.getUIElement(section_id).node.querySelector('input');
|
||||
|
||||
// Force enabled
|
||||
if (['trojan', 'anytls', 'tuic', 'hysteria', 'hysteria2', 'shadowquic', 'trusttunnel', 'masque'].includes(type)) {
|
||||
@@ -1315,6 +1484,87 @@ return view.extend({
|
||||
// @VMess-TLSmirror fields
|
||||
|
||||
/* VPN fields */
|
||||
so = ss.taboption('field_vpn', form.Flag, 'auto_firewall', _('Firewall'),
|
||||
_('Auto configure firewall'));
|
||||
so.default = so.enabled;
|
||||
so.validate = function(section_id, value) {
|
||||
const primary_port = this.section.getOption('zerotier_primary_port').formvalue(section_id);
|
||||
const secondary_port = this.section.getOption('zerotier_secondary_port').formvalue(section_id);
|
||||
const auto_firewall = this.getUIElement(section_id).node.querySelector('input');
|
||||
|
||||
// Force disabled
|
||||
if ((!primary_port || primary_port <= 0) && (!secondary_port || secondary_port <= 0)) {
|
||||
auto_firewall.checked = false;
|
||||
auto_firewall.disabled = true;
|
||||
} else
|
||||
auto_firewall.removeAttribute('disabled');
|
||||
|
||||
return true;
|
||||
}
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_vpn', form.Value, 'zerotier_primary_port', _('Listen port') + ' (%s)'.format(_('Primary')),
|
||||
_('%s UDP port. <code>0</code> selects an available port.').format(_('Primary')));
|
||||
so.datatype = 'port';
|
||||
so.placeholder = '9993';
|
||||
so.load = function(section_id) {
|
||||
const listen_port = this.map.data.get(this.section.config, section_id, 'zerotier_listen_port');
|
||||
const value = [
|
||||
this.map.data.get(this.section.config, section_id, 'zerotier_primary_port'),
|
||||
this.map.data.get(this.section.config, section_id, 'zerotier_secondary_port')
|
||||
].filter(Boolean).join(',');
|
||||
|
||||
if (listen_port !== value) {
|
||||
uci.set(this.section.config, section_id, 'zerotier_listen_port', value);
|
||||
uci.save();
|
||||
}
|
||||
|
||||
return form.Value.prototype.load.apply(this, arguments);
|
||||
}
|
||||
so.write = function(section_id, formvalue) {
|
||||
uci.set(this.section.config, section_id, 'zerotier_listen_port', [
|
||||
this.section.getOption('zerotier_primary_port').formvalue(section_id),
|
||||
this.section.getOption('zerotier_secondary_port').formvalue(section_id)
|
||||
].filter(Boolean).join(','));
|
||||
|
||||
return form.Value.prototype[formvalue ? 'write' : 'remove'].apply(this, arguments);
|
||||
}
|
||||
so.remove = so.write;
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_vpn', form.Value, 'zerotier_secondary_port', _('Listen port') + ' (%s)'.format(_('Secondary')),
|
||||
_('%s UDP port. <code>0</code> selects an available port.').format(_('Secondary')) + '</br>' +
|
||||
_('<code>-1</code> disables it.'));
|
||||
so.datatype = 'or(port, -1)';
|
||||
so.placeholder = '0';
|
||||
so.load = function(section_id) {
|
||||
const listen_port = this.map.data.get(this.section.config, section_id, 'zerotier_listen_port');
|
||||
const value = [
|
||||
this.map.data.get(this.section.config, section_id, 'zerotier_primary_port'),
|
||||
this.map.data.get(this.section.config, section_id, 'zerotier_secondary_port')
|
||||
].filter(Boolean).join(',');
|
||||
|
||||
if (listen_port !== value) {
|
||||
uci.set(this.section.config, section_id, 'zerotier_listen_port', value);
|
||||
uci.save();
|
||||
}
|
||||
|
||||
return form.Value.prototype.load.apply(this, arguments);
|
||||
}
|
||||
so.write = function(section_id, formvalue) {
|
||||
uci.set(this.section.config, section_id, 'zerotier_listen_port', [
|
||||
this.section.getOption('zerotier_primary_port').formvalue(section_id),
|
||||
this.section.getOption('zerotier_secondary_port').formvalue(section_id)
|
||||
].filter(Boolean).join(','));
|
||||
|
||||
return form.Value.prototype[formvalue ? 'write' : 'remove'].apply(this, arguments);
|
||||
}
|
||||
so.remove = so.write;
|
||||
so.depends('type', 'zerotier');
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_vpn', form.Value, 'endpoint_ip', _('Virtual address'),
|
||||
_('The %s address used by local machine in the %s network.').format(_('IPv4'), _('VPN')));
|
||||
so.datatype = 'or(ip4addr(1), cidr4)';
|
||||
@@ -1374,6 +1624,9 @@ return view.extend({
|
||||
|
||||
let def_mtu;
|
||||
switch (type) {
|
||||
case 'zerotier':
|
||||
def_mtu = '1400';
|
||||
break;
|
||||
case 'wireguard':
|
||||
def_mtu = '1408';
|
||||
break;
|
||||
@@ -1385,14 +1638,14 @@ return view.extend({
|
||||
|
||||
return true;
|
||||
}
|
||||
so.depends('type', 'wireguard');
|
||||
so.depends({type: /^(zerotier|wireguard)$/});
|
||||
so.depends({type: 'masque', masque_network: /^(|h2)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_vpn', form.Flag, 'endpoint_remote_dns_resolve', _('Remote DNS resolve'),
|
||||
_('Force DNS remote resolution.'));
|
||||
so.default = so.disabled;
|
||||
so.depends({type: /^(wireguard|masque)$/});
|
||||
so.depends({type: /^(zerotier|wireguard|masque)$/});
|
||||
so.modalonly = true;
|
||||
|
||||
so = ss.taboption('field_vpn', form.DynamicList, 'endpoint_dns', _('DNS server'));
|
||||
|
||||
+1253
-1044
File diff suppressed because it is too large
Load Diff
+1253
-1044
File diff suppressed because it is too large
Load Diff
+1253
-1044
File diff suppressed because it is too large
Load Diff
@@ -47,11 +47,16 @@ opmc() { # @less_25_12
|
||||
|
||||
# add_firewall
|
||||
add_firewall() {
|
||||
local enabled auto_firewall listen listen_port
|
||||
local enabled auto_firewall listen listen_port type
|
||||
config_get_bool enabled "$1" "enabled" "1"
|
||||
config_get_bool auto_firewall "$1" "auto_firewall" "1"
|
||||
config_get listen "$1" "listen" "::"
|
||||
config_get listen_port "$1" "listen_port"
|
||||
config_get type "$1" "type"
|
||||
|
||||
local "${type}_listen_port"
|
||||
config_get "${type}_listen_port" "$1" "${type}_listen_port"
|
||||
eval "listen_port=\"$listen_port,\$${type}_listen_port\""
|
||||
|
||||
[ "$enabled" = "0" ] && return 0
|
||||
[ "$auto_firewall" = "0" ] && return 0
|
||||
@@ -366,6 +371,7 @@ start_service() {
|
||||
json_add_array firewall
|
||||
# meta l4proto %s th dport %s counter accept comment "!%s: accept server instance [%s]"
|
||||
config_foreach add_firewall "inbound"
|
||||
config_foreach add_firewall "node"
|
||||
json_close_array
|
||||
procd_close_data
|
||||
|
||||
@@ -454,6 +460,10 @@ stop_service() {
|
||||
[ -z "$1" -o "$1" = "mihomo-c" ] && stop_client
|
||||
# Server
|
||||
[ -z "$1" -o "$1" = "mihomo-s" ] && stop_server
|
||||
# Directory
|
||||
#find "$RUN_DIR"/* -maxdepth 0 -type d -exec rm -rf "{}" \;
|
||||
# Resources
|
||||
rm -rf "$RUN_DIR"/*.lock
|
||||
# Setup firewall
|
||||
echo 2>"/dev/null" > "$RUN_DIR/fchomo_pre.nft"
|
||||
return 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Initialize necessary directories
|
||||
for d in certs provider ruleset resources templates; do
|
||||
for d in certs node provider ruleset resources templates; do
|
||||
mkdir -p "/etc/fchomo/$d/" 2>/dev/null
|
||||
done
|
||||
|
||||
|
||||
@@ -514,12 +514,14 @@ uci.foreach(uciconf, ucinode, (cfg) => {
|
||||
"target-rematch-name": cfg.target_rematch_name,
|
||||
"target-sub-rule": cfg.target_sub_rule,
|
||||
|
||||
/* HTTP / SOCKS / Shadowsocks / VMess / VLESS / Trojan / TUIC / hysteria2 */
|
||||
/* HTTP / SOCKS / Shadowsocks / VMess / VLESS / Trojan / TUIC / hysteria2 / ZeroTier / Tailscale / Masque */
|
||||
username: cfg.username,
|
||||
uuid: cfg.vmess_uuid || cfg.uuid,
|
||||
cipher: cfg.vmess_chipher || cfg.shadowsocks_chipher,
|
||||
password: cfg.shadowsocks_password || cfg.password,
|
||||
headers: cfg.headers ? json(cfg.headers) : null,
|
||||
network: cfg.zerotier_network_id || cfg.masque_network || null,
|
||||
"state-dir": `${HM_DIR}/${ucinode}/${cfg['.name']}`,
|
||||
|
||||
/* Shadowsocks */
|
||||
|
||||
@@ -627,14 +629,50 @@ uci.foreach(uciconf, ucinode, (cfg) => {
|
||||
"health-check": cfg.type === 'trusttunnel' ? (cfg.trusttunnel_health_check === '0' ? false : true) : null,
|
||||
quic: strToBool(cfg.trusttunnel_quic),
|
||||
|
||||
/* ZeroTier */
|
||||
"primary-port": strToInt(cfg.zerotier_primary_port),
|
||||
"secondary-port": strToInt(cfg.zerotier_secondary_port),
|
||||
"physical-mtu": strToInt(cfg.zerotier_physical_mtu) || null,
|
||||
"tcp-fallback-mode": cfg.zerotier_fallback_mode,
|
||||
"tcp-fallback-relay": cfg.zerotier_fallback_relay,
|
||||
"remote-trace-target": cfg.zerotier_trace_target,
|
||||
"remote-trace-level": strToInt(cfg.zerotier_trace_level),
|
||||
"low-bandwidth": strToBool(cfg.zerotier_low_bandwidth),
|
||||
"encrypted-hello": strToBool(cfg.zerotier_encrypted_hello),
|
||||
//planet: `${HM_DIR}/${ucinode}/${cfg['.name']}/planet`,
|
||||
...(isEmpty(cfg.zerotier_orbit) ? {} : {
|
||||
orbit: map([0], () => {
|
||||
const orbits = [];
|
||||
for (let orbit in cfg.zerotier_orbit) {
|
||||
orbit = split(orbit, ':');
|
||||
const world = shift(orbit);
|
||||
for (let seed in orbit)
|
||||
push(orbits, {world: world, seed: seed});
|
||||
}
|
||||
return orbits;
|
||||
})[0]
|
||||
}),
|
||||
"ip-stack": cfg.zerotier_ipstack ? {
|
||||
mode: cfg.zerotier_ipstack,
|
||||
"congestion-controller": replace(cfg.congestion_controller, 'new_reno', 'reno')
|
||||
} : null,
|
||||
|
||||
/* WireGuard */
|
||||
"pre-shared-key": cfg.wireguard_pre_shared_key,
|
||||
"allowed-ips": cfg.wireguard_allowed_ips,
|
||||
reserved: cfg.wireguard_reserved,
|
||||
"persistent-keepalive": strToInt(cfg.wireguard_persistent_keepalive),
|
||||
|
||||
/* Tailscale */
|
||||
hostname: cfg.tailscale_hostname,
|
||||
"auth-key": cfg.tailscale_auth_key,
|
||||
"control-url": cfg.tailscale_control_url,
|
||||
ephemeral: strToBool(cfg.tailscale_ephemeral),
|
||||
"accept-routes": strToBool(cfg.tailscale_accept_routes),
|
||||
"exit-node": cfg.tailscale_exit_node,
|
||||
"exit-node-allow-lan-access": strToBool(cfg.tailscale_exit_node_allow_lan_access),
|
||||
|
||||
/* Masque */
|
||||
network: cfg.masque_network || null,
|
||||
|
||||
/* SSH */
|
||||
"private-key-passphrase": cfg.ssh_priv_key_passphrase,
|
||||
@@ -645,7 +683,7 @@ uci.foreach(uciconf, ucinode, (cfg) => {
|
||||
"udp-over-stream": strToBool(cfg.shadowquic_udp_over_stream || cfg.tuic_udp_over_stream),
|
||||
"heartbeat-interval": strToInt(cfg.tuic_heartbeat) || null,
|
||||
"keep-alive-interval": strToInt(cfg.shadowquic_heartbeat) || null,
|
||||
"congestion-controller": cfg.congestion_controller,
|
||||
"congestion-controller": cfg.type in ['zerotier'] ? null : cfg.congestion_controller,
|
||||
"bbr-profile": cfg.bbr_profile,
|
||||
"max-open-streams": strToInt(cfg.max_open_streams) || null,
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ function wGET(url, header, filepath) {
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
const RES_TYPE = ['certs', 'provider', 'ruleset', 'resources', 'templates'];
|
||||
const RES_TYPE = ['certs', 'node', 'provider', 'ruleset', 'resources', 'templates'];
|
||||
|
||||
const methods = {
|
||||
mihomo_generator: {
|
||||
@@ -330,7 +330,7 @@ const methods = {
|
||||
},
|
||||
|
||||
file_read: {
|
||||
args: { type: 'type', filename: 'filename' },
|
||||
args: { type: 'type', filename: 'filename', isbinary: 'isbinary' },
|
||||
call: function(req) {
|
||||
if (!(req.args?.type in RES_TYPE))
|
||||
return { content: null, error: 'illegal type' };
|
||||
@@ -338,13 +338,17 @@ const methods = {
|
||||
if ((!req.args?.filename) || match(req.args?.filename, /\.\.\//))
|
||||
return { content: null, error: 'illegal filename' };
|
||||
|
||||
const filecontent = readfile(`${HM_DIR}/${req.args?.type}/${req.args?.filename}`);
|
||||
let filecontent = readfile(`${HM_DIR}/${req.args?.type}/${req.args?.filename}`);
|
||||
|
||||
if (req.args?.isbinary == 1)
|
||||
filecontent = b64enc(filecontent);
|
||||
|
||||
return { content: filecontent };
|
||||
}
|
||||
},
|
||||
|
||||
file_write: {
|
||||
args: { type: 'type', filename: 'filename', content: 'content' },
|
||||
args: { type: 'type', filename: 'filename', content: 'content', isbinary: 'isbinary' },
|
||||
call: function(req) {
|
||||
if (!(req.args?.type in RES_TYPE))
|
||||
return { result: false, error: 'illegal type' };
|
||||
@@ -363,6 +367,9 @@ const methods = {
|
||||
content += '\n';
|
||||
}
|
||||
|
||||
if (req.args?.isbinary == 1)
|
||||
content = b64dec(content);
|
||||
|
||||
//system(`mkdir -p ${HM_DIR}/${req.args?.type}`);
|
||||
writefile(file, content);
|
||||
|
||||
@@ -403,7 +410,7 @@ const methods = {
|
||||
if ((!req.args?.filename) || match(req.args?.filename, /\.\.\//))
|
||||
return { result: false, error: 'illegal filename' };
|
||||
|
||||
system(`rm -f ${HM_DIR}/${req.args?.type}/${shellQuote(req.args?.filename)}`);
|
||||
system(`rm -rf ${HM_DIR}/${req.args?.type}/${shellQuote(req.args?.filename)}`);
|
||||
|
||||
return { result: true };
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.2-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for FeiShuVpn
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -35,7 +35,7 @@ o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||
o.default = "9091"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o.default = "registry.cn-qingdao.aliyuncs.com/feishuwg/p2p:latest"
|
||||
|
||||
@@ -13,6 +13,9 @@ msgstr "飞鼠组网是一个点对点的组网工具。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.3-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.3-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for Gogs
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -28,7 +28,7 @@ o.default = "3022"
|
||||
o.datatype = "string"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("gogs/gogs:latest", "gogs/gogs:latest")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "Gogs 是一个轻松易用的 Git 服务。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "HTTP Port"
|
||||
msgstr "HTTP 端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.1.4-r20250321
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.1.4-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for homeassistant
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -18,7 +18,7 @@ s = m:section(TypedSection, "homeassistant", translate("Setup"), translate("The
|
||||
s.addremove=false
|
||||
s.anonymous=true
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("homeassistant/home-assistant:latest", "homeassistant/home-assistant:latest")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "将本地控制和隐私放在首位的开源家庭自动化,由全世
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Service Status"
|
||||
msgstr "服务状态"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.2-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for HTReader
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -47,7 +47,7 @@ o = s:option(Value, "active_code", translate("Active code"))
|
||||
o.datatype = "string"
|
||||
o:depends("multiuser", 1)
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o.default = "hectorqin/reader"
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "HTReader 是一个网页版本在线读书。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.2-r20250321
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for Immich
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -35,7 +35,7 @@ o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||
o.default = "2283"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_ver", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_ver", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o.default = "release"
|
||||
|
||||
@@ -13,6 +13,9 @@ msgstr "Immich 是私有化的相册视频管理工具。很占资源,网络
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.1.7-r20241211
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.1.7-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for istoredup
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -31,7 +31,7 @@ s = m:section(TypedSection, "istoredup", translate("Setup"),
|
||||
s.addremove=false
|
||||
s.anonymous=true
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("linkease/istoreduprk35xx:latest", "linkease/istoreduprk35xx:latest")
|
||||
|
||||
@@ -7,6 +7,9 @@ msgstr "官方网站:"
|
||||
msgid "A duplica of iStoreOS."
|
||||
msgstr "iStoreOS 的分身,可以把风险高的软件安装到分身里面,出问题不影响到主系统。"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Service Status"
|
||||
msgstr "服务状态"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.6-r20250406
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.6-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for 1Panel
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -52,7 +52,7 @@ o:value("v1.10.11-lts", "v1.10.11-lts")
|
||||
o:value("v1.10.28-lts", "v1.10.28-lts")
|
||||
o.default = 'v1.10.28-lts'
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("linkease/istorepanel:latest", "linkease/istorepanel:latest")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "1Panel 是新一代的 Linux 服务器运维管理面板"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.4-r20250321
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.4-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for ITTools
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -35,7 +35,7 @@ o.default = "9070"
|
||||
o.datatype = "port"
|
||||
o:depends("hostnet", 0)
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o.default = "corentinth/it-tools:latest"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "ITTools"
|
||||
msgid "开发工具集"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.1.1-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.1.1-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for jackett
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -23,7 +23,7 @@ o.rmempty = false
|
||||
o.default = "9117"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("linuxserver/jackett:latest", "linuxserver/jackett:latest")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "Jackett 是维护索引器抓取和翻译逻辑的单一存储库 - 消
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Torrent save path"
|
||||
msgstr "种子保存路径"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.2.2-r20250321
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.2.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for jellyfin
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -27,7 +27,7 @@ s = m:section(TypedSection, "jellyfin", translate("Setup"),
|
||||
s.addremove=false
|
||||
s.anonymous=true
|
||||
|
||||
o = s:option(Value, "image", translate("Image"))
|
||||
o = s:option(Value, "image", translate("Docker Image"))
|
||||
o.datatype = "string"
|
||||
o:value("", translate("Default"))
|
||||
if luci.sys.call("grep -q 'rockchip,' /proc/device-tree/compatible 2>/dev/null") == 0 then
|
||||
|
||||
@@ -22,7 +22,7 @@ msgstr "x86 系列"
|
||||
msgid "Raspberry Pi series"
|
||||
msgstr "树莓派系列"
|
||||
|
||||
msgid "Image"
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Default"
|
||||
|
||||
@@ -9,7 +9,7 @@ LUCI_TITLE:=LuCI support for KodExplorer
|
||||
LUCI_DEPENDS:=+nginx-ssl +unzip +zoneinfo-asia +php8 +php8-fastcgi +php8-fpm +php8-mod-curl +php8-mod-dom +php8-mod-gd +php8-mod-iconv +php8-mod-mbstring +php8-mod-opcache +php8-mod-session +php8-mod-zip +php8-mod-sqlite3 +php8-mod-pdo +php8-mod-pdo-sqlite +php8-mod-pdo-mysql +php8-mod-xml +php8-mod-xmlreader +php8-mod-xmlwriter
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=20220109
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@@ -1,19 +1,4 @@
|
||||
#!/bin/sh
|
||||
[ ! -f "/usr/share/ucitrack/luci-app-kodexplorer.json" ] && {
|
||||
cat > /usr/share/ucitrack/luci-app-kodexplorer.json << EEOF
|
||||
{
|
||||
"config": "kodexplorer",
|
||||
"init": "kodexplorer"
|
||||
}
|
||||
EEOF
|
||||
}
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@kodexplorer[-1]
|
||||
add ucitrack kodexplorer
|
||||
set ucitrack.@kodexplorer[-1].init=kodexplorer
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
/etc/init.d/php8-fpm stop
|
||||
/etc/init.d/php8-fpm disable
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.1-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.1-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for LANraragi
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -24,7 +24,7 @@ o.rmempty = false
|
||||
o.default = "3000"
|
||||
o.datatype = "string"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("dezhao/lanraragi_cn", "dezhao/lanraragi_cn")
|
||||
|
||||
@@ -13,6 +13,9 @@ msgstr "配置文件路径"
|
||||
msgid "Content path"
|
||||
msgstr "资源路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "HTTP Port"
|
||||
msgstr "HTTP 端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.2-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for Memos
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -22,7 +22,7 @@ o = s:option(Value, "http_port", translate("HTTP Port").."<b>*</b>")
|
||||
o.default = "5230"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("neosmemo/memos:latest", "neosmemo/memos:latest")
|
||||
|
||||
@@ -13,6 +13,9 @@ msgstr "Memos 是一个开源的极简的碎片化知识管理工具。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "HTTP Port"
|
||||
msgstr "HTTP 端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.2-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for MTPhotos
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -36,7 +36,7 @@ o.default = "8063"
|
||||
o.datatype = "port"
|
||||
o:depends("hostnet", 0)
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("mtphotos/mt-photos:nodb-latest", "mtphotos/mt-photos:nodb-latest")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "MTPhotos 是一个相册管理软件。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Upload path"
|
||||
msgstr "上传文件路径"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.1.3-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.1.3-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for nastools
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -23,7 +23,7 @@ o.rmempty = false
|
||||
o.default = "3003"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("jxxghp/nas-tools", "jxxghp/nas-tools")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "NasTools 是汇聚了电影搜索,下载,订阅,观看等等 NAS
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.1-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.1-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for Navidrome
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -23,7 +23,7 @@ o.rmempty = false
|
||||
o.default = "3000"
|
||||
o.datatype = "string"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("difegue/navidrome", "difegue/navidrome")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "Navidrome 是一个开源的在线音乐播放软件。"
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Music path"
|
||||
msgstr "音乐路径"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.1.1-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.1.1-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for nextcloud
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -23,7 +23,7 @@ o.rmempty = false
|
||||
o.default = "8082"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("nextcloud", "nextcloud")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "所有数据的安全之家。 根据您的条件,从任何设备访
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.26.1
|
||||
PKG_RELEASE:=7
|
||||
PKG_RELEASE:=8
|
||||
|
||||
LUCI_TITLE:=LuCI Support for nikki
|
||||
LUCI_DEPENDS:=+luci-base +nikki
|
||||
|
||||
@@ -82,7 +82,7 @@ const methods = {
|
||||
|
||||
const protocol = api_tls_listen ? 'https' : 'http';
|
||||
|
||||
const url = api_listen + path;
|
||||
const url = (api_tls_listen ?? api_listen) + path;
|
||||
|
||||
const process = popen(`curl --proto-default '${protocol}' --insecure --request '${method}' --oauth2-bearer '${api_secret}' --url-query '${query}' --data '${body}' '${url}'`);
|
||||
if (process) {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.1-r20250403
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.1-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for OneAPI
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -36,7 +36,7 @@ o.default = "3005"
|
||||
o.datatype = "port"
|
||||
o:depends("hostnet", 0)
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("justsong/one-api:latest", "justsong/one-api:latest")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "OneAPI 是LLM API 管理 & 分发系统,支持 OpenAI、Azure、Anthro
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.8-r20250207
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.8-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for OpenWebUI
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -35,7 +35,7 @@ o = s:option(Value, "port", translate("Port").."<b>*</b>")
|
||||
o.default = "3000"
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>")
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("ghcr.io/open-webui/open-webui:main", "ghcr.io/open-webui/open-webui:main")
|
||||
|
||||
@@ -10,6 +10,9 @@ msgstr "Open WebUI 是一款可扩展、自托管的 AI 界面,能够无缝适
|
||||
msgid "Config path"
|
||||
msgstr "配置文件路径"
|
||||
|
||||
msgid "Docker Image"
|
||||
msgstr "镜像"
|
||||
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_VERSION:=1.0.2-r20240822
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=1.0.2-r20260804
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI support for Owntone
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
@@ -18,7 +18,7 @@ s = m:section(TypedSection, "main", translate("Setup"), translate("The following
|
||||
s.addremove=false
|
||||
s.anonymous=true
|
||||
|
||||
o = s:option(Value, "image_name", translate("Image").."<b>*</b>", translate("Owntone only works in host network with port 3689"))
|
||||
o = s:option(Value, "image_name", translate("Docker Image").."<b>*</b>", translate("Owntone only works in host network with port 3689"))
|
||||
o.rmempty = false
|
||||
o.datatype = "string"
|
||||
o:value("lscr.io/linuxserver/daapd:latest", "lscr.io/linuxserver/daapd:latest")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user