update 2026-10-26 17:35:19

This commit is contained in:
action committed 2026-10-26 17:35:19 +08:00
1 parent 2f2bfddf57
commit 8de6b6ed73
31 files changed
+1833 -486

No files matched your search

+50 -12
View File
@@ -1,19 +1,20 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=clashoo
PKG_SHORT_SHA:=6780eee
PKG_COMMIT_DATE:=2026.10.25
PKG_UPSTREAM_VERSION:=1.19.33
PKG_UPSTREAM_TAG:=v$(PKG_UPSTREAM_VERSION)
PKG_SHORT_SHA:=3f27ef3
PKG_VERSION:=$(PKG_COMMIT_DATE)~$(PKG_SHORT_SHA)
PKG_RELEASE:=3
PKG_VERSION:=2026.10.25.$(PKG_UPSTREAM_VERSION)
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA).tar.gz
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-alpha-$(PKG_SHORT_SHA)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-alpha-$(PKG_SHORT_SHA)
PKG_SOURCE:=$(PKG_NAME)-stable-$(PKG_UPSTREAM_TAG)-$(PKG_SHORT_SHA).tar.gz
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-stable-$(PKG_UPSTREAM_TAG)-$(PKG_SHORT_SHA)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-clashoo/releases/download/mihomo-src
PKG_SOURCE_VERSION:=6780eeeb27c7eda5e79a6310a4f7f91ba7cb725d
PKG_HASH:=affb9e916e750c6bd4385c6718660a02cc213936063141fd1c2422011e408b47
PKG_BUILD_VERSION:=alpha-$(PKG_SHORT_SHA)
PKG_SOURCE_VERSION:=3f27ef39f8c96bbfbc8b0b9bb10f5c9ef60149d8
PKG_HASH:=1ef7a4087f3805bd2624a940e2e43a0bc23719a25465c9f503aa6c11572f1321
PKG_BUILD_VERSION:=$(PKG_UPSTREAM_TAG)
PKG_LICENSE:=GPL3.0+
PKG_MAINTAINER:=kenzok8
@@ -50,8 +51,11 @@ endef
define Package/clashoo/install
$(call GoPackage/Package/Install/Bin,$(1))
$(INSTALL_DIR) $(1)/usr/libexec/clashoo
$(INSTALL_DIR) $(1)/usr/bin
ln -sf /usr/bin/mihomo $(1)/usr/bin/clash-meta
mv -f $(1)/usr/bin/mihomo $(1)/usr/libexec/clashoo/mihomo-stable
ln -sf /usr/libexec/clashoo/mihomo-stable $(1)/usr/bin/mihomo
ln -sf /usr/libexec/clashoo/mihomo-stable $(1)/usr/bin/clash-meta
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_DIR) $(1)/etc/config
@@ -82,10 +86,44 @@ define Package/clashoo/install
$(RM) $(1)/usr/share/clashoo/core_down_complete
endef
define Package/clashoo/preinst
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
save_core() {
src="$$1"
dst="$$2"
[ -f "$$src" ] && [ ! -L "$$src" ] || return 0
if [ -e "$$dst" ] || [ -L "$$dst" ]; then return 0; fi
mkdir -p "$$(dirname "$$dst")" || return 1
tmp="$$dst.tmp.$$$$"
cp "$$src" "$$tmp" && chmod 0755 "$$tmp" && cmp -s "$$src" "$$tmp" || {
rm -f "$$tmp"
return 1
}
if command -v sha256sum >/dev/null 2>&1; then
old_hash="$$(sha256sum "$$src" | awk '{print $$1}')"
new_hash="$$(sha256sum "$$tmp" | awk '{print $$1}')"
[ "$$old_hash" = "$$new_hash" ] || {
rm -f "$$tmp"
return 1
}
fi
mv -f "$$tmp" "$$dst"
}
save_core /usr/bin/mihomo /usr/share/clashoo/bin/mihomo-alpha || exit 1
save_core /usr/bin/mihomo-stable /usr/share/clashoo/bin/mihomo-stable || exit 1
if [ -x /usr/bin/clash-meta ] && [ ! -L /usr/bin/clash-meta ] && [ ! -e /usr/share/clashoo/bin/mihomo-stable ]; then
if ! /usr/bin/clash-meta -v 2>/dev/null | grep -Eiq '(alpha|beta|rc|pre|smart)'; then
save_core /usr/bin/clash-meta /usr/share/clashoo/bin/mihomo-stable || exit 1
fi
fi
fi
exit 0
endef
define Package/clashoo/postinst
#!/bin/sh
if [ -z "$${IPKG_INSTROOT}" ]; then
[ -x /usr/bin/mihomo ] && [ ! -x /usr/bin/clash-meta ] && ln -sf /usr/bin/mihomo /usr/bin/clash-meta
rm -f /usr/share/clashoo/check_luci_version.sh /usr/share/clashoo/check_clash_meta_version.sh /usr/share/clashoo/check_mihomo_core_version.sh
rm -f /usr/share/clashoo/cuslist.sh /usr/share/clashoo/groups.sh /usr/share/clashoo/load_groups.sh /usr/share/clashoo/panel_diag.sh
rm -f /usr/share/clashoo/rmlist.sh /usr/share/clashoo/uplist.sh /usr/share/clashoo/rpc_restart_async.sh /usr/share/clashoo/rpc_update_china_ip_async.sh
+2 -2
View File
@@ -9,7 +9,7 @@ config clashoo 'config'
option dash_port '9090'
option dashboard_panel 'zashboard'
option level 'info'
option core '3'
option core '2'
option allow_lan '1'
option dnsforwader '1'
option subcri 'meta'
@@ -28,7 +28,7 @@ config clashoo 'config'
option listen_port '1053'
option interf '0'
option download_core 'amd64-compatible'
option dcore '3'
option dcore '2'
option same_tag '1'
option geoip_source '3'
option geoip_format 'mmdb'
+47 -37
View File
@@ -169,43 +169,54 @@ cleanup_stale_core_nft() {
}
_core_candidates() {
echo "/usr/bin/mihomo-stable /usr/bin/mihomo /usr/bin/clash-meta /etc/clashoo/clash"
echo "/usr/share/clashoo/bin/mihomo-stable /usr/libexec/clashoo/mihomo-stable /usr/share/clashoo/bin/mihomo-alpha /usr/bin/mihomo /usr/bin/clash-meta /etc/clashoo/clash"
}
_migrate_legacy_mihomo_stable() {
local legacy=/usr/bin/clash-meta version
[ -x /usr/bin/mihomo-stable ] && return 0
local legacy=/usr/bin/clash-meta target=/usr/share/clashoo/bin/mihomo-stable version staged
[ -x "$target" ] && return 0
[ -x "$legacy" ] && [ ! -L "$legacy" ] || return 0
version=$("$legacy" -v 2>/dev/null | head -n 1)
[ -n "$version" ] || return 0
echo "$version" | grep -Eiq '(alpha|beta|rc|pre|smart)' && return 0
cp -f "$legacy" /usr/bin/mihomo-stable 2>/dev/null && chmod 0755 /usr/bin/mihomo-stable
mkdir -p "$(dirname "$target")" || return 1
staged="${target}.$$"
cp -f "$legacy" "$staged" 2>/dev/null && chmod 0755 "$staged" && mv -f "$staged" "$target"
}
_fallback_missing_mihomo_core() {
local selected fallback
is_singbox_selected && return 0
selected="$(uci -q get clashoo.config.core 2>/dev/null)"
case "$selected" in
2)
[ -x /usr/bin/mihomo-stable ] && return 0
[ -x /usr/bin/mihomo ] || return 0
fallback=3
;;
3)
[ -x /usr/bin/mihomo ] && return 0
[ -x /usr/bin/mihomo-stable ] || return 0
fallback=2
;;
*) return 0 ;;
esac
uci -q set clashoo.config.core="$fallback"
uci -q set clashoo.config.dcore="$fallback"
uci -q commit clashoo >/dev/null 2>&1
if [ "$fallback" = "3" ]; then
log_msg "Stable core missing, falling back to Alpha" "稳定版内核缺失,自动回退到 Alpha"
_mihomo_stable_binary() {
local bundled=/usr/libexec/clashoo/mihomo-stable manual=/usr/share/clashoo/bin/mihomo-stable bundled_ver manual_ver
# A successful custom download is an explicit override, even if its version is older.
if [ -x "$manual" ] &&
[ "$(sed -n '1{s/^[[:space:]]*//;s/[[:space:]]*$//;p;}' /usr/share/clashoo/clash_meta_version 2>/dev/null)" = "custom-url" ]; then
echo "$manual"
return 0
fi
[ -x "$bundled" ] || { [ -x "$manual" ] && { echo "$manual"; return 0; }; return 1; }
[ -x "$manual" ] || { echo "$bundled"; return; }
bundled_ver="$("$bundled" -v 2>/dev/null | awk '{for (i = 1; i < NF; i++) if ($i == "Meta") {print $(i + 1); exit}}')"
manual_ver="$("$manual" -v 2>/dev/null | awk '{for (i = 1; i < NF; i++) if ($i == "Meta") {print $(i + 1); exit}}')"
bundled_ver="${bundled_ver#v}"
manual_ver="${manual_ver#v}"
printf '%s\n' "$bundled_ver" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' || bundled_ver=""
printf '%s\n' "$manual_ver" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' || manual_ver=""
if [ -n "$bundled_ver" ] && [ -n "$manual_ver" ]; then
if awk -v manual="$manual_ver" -v bundled="$bundled_ver" 'BEGIN {
split(manual, m, "."); split(bundled, b, ".");
for (i = 1; i <= 3; i++) {
if (m[i] + 0 > b[i] + 0) exit 0;
if (m[i] + 0 < b[i] + 0) exit 1;
}
exit 0;
}'; then
echo "$manual"
else
echo "$bundled"
fi
elif [ -n "$manual_ver" ]; then
echo "$manual"
else
log_msg "Alpha core missing, falling back to stable" "Alpha 内核缺失,自动回退到稳定版"
echo "$bundled"
fi
}
@@ -220,11 +231,11 @@ _detect_selected_core() {
return 1
;;
2|mihomo)
[ -x /usr/bin/mihomo-stable ] && echo /usr/bin/mihomo-stable && return
return 1
_mihomo_stable_binary
return $?
;;
3|mihomo-alpha)
[ -x /usr/bin/mihomo ] && echo /usr/bin/mihomo && return
[ -x /usr/share/clashoo/bin/mihomo-alpha ] && echo /usr/share/clashoo/bin/mihomo-alpha && return
return 1
;;
esac
@@ -233,7 +244,7 @@ _detect_selected_core() {
core_supports_advanced_features() {
case "$CLASH" in
*/mihomo|*/mihomo-stable|*/clash-meta|*/smart)
*/mihomo|*/mihomo-stable|*/mihomo-alpha|*/clash-meta|*/smart)
return 0
;;
*)
@@ -2126,12 +2137,12 @@ _start_validate_core() {
echo "Clashoo" > "$REAL_LOG"
return 1
elif [ "${core:-0}" -eq 2 ] && [ ! -x "$CLASH" ]; then
log_msg "mihomo core not found, detected binary is unavailable: $CLASH" "找不到可用的 mihomo 内核: $CLASH"
log_msg "mihomo stable core not found, detected binary is unavailable: $CLASH" "找不到可用的 mihomo 稳定版内核: $CLASH"
sleep 1
echo "Clashoo" > "$REAL_LOG"
return 1
elif [ "${core:-0}" -eq 3 ] && [ ! -x "$CLASH" ]; then
log_msg "mihomo core not found, detected binary is unavailable: $CLASH" "找不到可用的 mihomo 内核: $CLASH"
log_msg "mihomo Alpha core not found, detected binary is unavailable: $CLASH" "找不到可用的 mihomo Alpha 内核,请在组件更新中安装: $CLASH"
sleep 1
echo "Clashoo" > "$REAL_LOG"
return 1
@@ -2167,10 +2178,10 @@ _start_prepare_config() {
if { egrep -q '^ {0,}rule-providers:' "$CONFIG_YAML" || egrep -q '^ {0,}script:' "$CONFIG_YAML"; } && ! core_supports_advanced_features; then
[ "$_reload_candidate" = "1" ] && return 1
if [ -x /usr/bin/mihomo ]; then
uci set clashoo.config.core="3" && uci commit clashoo
elif [ -x /usr/bin/mihomo-stable ]; then
if [ -n "$(_mihomo_stable_binary)" ]; then
uci set clashoo.config.core="2" && uci commit clashoo
elif [ -x /usr/share/clashoo/bin/mihomo-alpha ]; then
uci set clashoo.config.core="3" && uci commit clashoo
else
log_msg "Current config requires mihomo/clash-meta core" "当前配置需要 mihomo 或 clash-meta 内核"
backend_remove_rules >/dev/null 2>&1
@@ -2407,7 +2418,6 @@ start_service(){
sync_legacy_core_field
_migrate_legacy_mihomo_stable
_fallback_missing_mihomo_core
CLASH="$(_detect_selected_core)"
cleanup_legacy_startup_backups
@@ -120,7 +120,6 @@ set clashoo_china6 {
2400:5280:1400::/38,
2400:5280:1c00::/38,
2400:5280:3400::/38,
2400:5280:4c00::/38,
2400:5280:5000::/36,
2400:5280:6000::/35,
2400:5280:8000::/34,
@@ -962,6 +961,7 @@ set clashoo_china6 {
2402:7d80::/32,
2402:7da0::/32,
2402:7e20::/32,
2402:7ee0::/32,
2402:8180::/32,
2402:8300::/32,
2402:8380::/32,
@@ -1791,7 +1791,11 @@ set clashoo_china6 {
2405:84c0:8050::/48,
2405:84c0:8053::/48,
2405:84c0:8058::/45,
2405:84c0:8060::/43,
2405:84c0:8061::/48,
2405:84c0:8062::/47,
2405:84c0:8064::/46,
2405:84c0:8068::/45,
2405:84c0:8070::/44,
2405:84c0:8080::/41,
2405:84c0:8100::/40,
2405:84c0:8200::/39,
@@ -2050,7 +2054,10 @@ set clashoo_china6 {
2406:840:8a0::/43,
2406:840:8c0::/42,
2406:840:900::/40,
2406:840:a00::/44,
2406:840:a01::/48,
2406:840:a02::/47,
2406:840:a04::/46,
2406:840:a08::/45,
2406:840:a12::/47,
2406:840:a14::/46,
2406:840:a18::/45,
@@ -2248,7 +2255,8 @@ set clashoo_china6 {
2406:840:9610::/44,
2406:840:9630::/44,
2406:840:9640::/43,
2406:840:9660::/46,
2406:840:9660::/48,
2406:840:9662::/47,
2406:840:9664::/47,
2406:840:9667::/48,
2406:840:9668::/45,
@@ -2272,6 +2280,7 @@ set clashoo_china6 {
2406:840:9900::/42,
2406:840:9940::/43,
2406:840:9960::/47,
2406:840:9963::/48,
2406:840:9965::/48,
2406:840:9968::/46,
2406:840:996d::/48,
@@ -3144,8 +3153,7 @@ set clashoo_china6 {
240b:4006::/48,
240b:4006:1000::/43,
240b:4006:1020::/44,
240b:4006:1100::/45,
240b:4006:110c::/46,
240b:4006:1100::/44,
240b:4006:1110::/45,
240b:4006:1118::/46,
240b:4007::/32,
@@ -3261,8 +3269,6 @@ set clashoo_china6 {
2605:9d80:9042::/48,
2605:9d80:9071::/48,
2605:9d80:9092::/48,
2620:57:4004::/47,
2804:1e48:9002::/48,
2a03:f900::/29,
2a04:3e00::/48,
2a04:3e00:2::/47,
@@ -394,16 +394,13 @@ set clashoo_china {
43.92.0.0/15,
43.94.0.0/18,
43.96.0.0/23,
43.96.2.130/32,
43.96.3.0/24,
43.96.4.0/22,
43.96.8.0/22,
43.96.16.130/32,
43.96.18.0/24,
43.96.20.0/22,
43.96.24.0/22,
43.96.32.0/22,
43.96.36.130/32,
43.96.40.0/24,
43.96.42.0/24,
43.96.44.0/23,
@@ -414,7 +411,6 @@ set clashoo_china {
43.96.62.0/23,
43.96.64.0/21,
43.96.72.0/22,
43.96.77.131/32,
43.96.78.0/24,
43.96.80.0/23,
43.96.85.0/24,
@@ -459,8 +455,7 @@ set clashoo_china {
43.123.0.0/17,
43.123.128.0/18,
43.124.0.0/16,
43.125.0.0/20,
43.125.24.0/21,
43.125.0.0/19,
43.125.32.0/20,
43.125.48.0/21,
43.126.0.0/17,
@@ -805,6 +800,7 @@ set clashoo_china {
45.117.68.0/22,
45.117.124.0/22,
45.117.252.0/22,
45.119.42.0/23,
45.119.60.0/22,
45.119.64.0/21,
45.119.72.0/22,
@@ -1124,6 +1120,7 @@ set clashoo_china {
47.246.192.0/20,
47.246.208.0/23,
47.246.212.0/22,
47.246.216.0/22,
47.250.0.0/18,
47.250.68.0/22,
47.250.72.0/21,
@@ -1478,8 +1475,7 @@ set clashoo_china {
103.8.108.0/22,
103.8.156.0/22,
103.8.200.0/21,
103.8.221.0/24,
103.8.222.0/23,
103.8.220.0/22,
103.9.8.0/22,
103.9.24.0/22,
103.9.108.0/22,
@@ -2113,7 +2109,6 @@ set clashoo_china {
103.89.184.0/21,
103.89.192.0/19,
103.89.224.0/21,
103.90.51.0/24,
103.90.52.0/22,
103.90.56.0/23,
103.90.92.0/22,
@@ -2683,6 +2678,7 @@ set clashoo_china {
103.186.228.0/23,
103.189.92.0/23,
103.189.152.0/22,
103.189.197.0/24,
103.190.20.0/23,
103.190.71.0/24,
103.190.104.0/23,
@@ -4062,10 +4058,6 @@ set clashoo_china {
124.67.0.0/16,
124.68.16.0/20,
124.68.64.0/18,
124.68.176.0/20,
124.68.224.0/20,
124.68.244.0/22,
124.68.248.0/21,
124.69.0.0/16,
124.70.0.0/16,
124.71.0.0/17,
@@ -4445,6 +4437,7 @@ set clashoo_china {
160.202.62.0/24,
160.202.148.0/22,
160.202.152.0/22,
160.202.210.0/23,
160.202.212.0/22,
160.202.216.0/21,
160.202.224.0/19,
@@ -4741,6 +4734,7 @@ set clashoo_china {
192.140.160.0/19,
192.140.192.0/20,
192.140.208.0/21,
192.140.244.0/23,
192.144.128.0/17,
192.163.11.0/24,
192.232.34.0/23,
@@ -6497,12 +6491,14 @@ set clashoo_china {
223.112.0.0/14,
223.116.0.0/15,
223.121.128.0/17,
223.122.4.0/22,
223.122.12.0/22,
223.122.5.0/24,
223.122.6.0/23,
223.122.13.0/24,
223.122.14.0/23,
223.122.18.0/23,
223.122.20.0/22,
223.122.26.0/23,
223.122.28.0/22,
223.122.28.0/23,
223.123.196.0/22,
223.123.204.0/22,
223.123.208.0/20,
Binary file not shown.
Binary file not shown.
@@ -1062,10 +1062,10 @@ if [ -n "$CUSTOM_CORE_URL" ]; then
write_log "使用自定义内核下载链接"
URL="$CUSTOM_CORE_URL"
if [ "$CORETYPE" = "3" ]; then
TARGET="/usr/bin/mihomo"
TARGET="/usr/share/clashoo/bin/mihomo-alpha"
VERSION_FILE="/usr/share/clashoo/mihomo_version"
else
TARGET="/usr/bin/mihomo-stable"
TARGET="/usr/share/clashoo/bin/mihomo-stable"
VERSION_FILE="/usr/share/clashoo/clash_meta_version"
fi
TAG="custom"
@@ -1175,7 +1175,7 @@ elif [ "$CORETYPE" = "2" ]; then
[ -z "$TAG" ] && write_log "获取稳定版版本号失败" && exit 1
ASSET=$(pick_mihomo_asset "MetaCubeX/mihomo" "$TAG" "$(map_mihomo_arch "$MODELTYPE")" "stable")
URL="https://github.com/MetaCubeX/mihomo/releases/download/${TAG}/${ASSET}"
TARGET="/usr/bin/mihomo-stable"
TARGET="/usr/share/clashoo/bin/mihomo-stable"
VERSION_FILE="/usr/share/clashoo/clash_meta_version"
VERSION_VALUE="$TAG"
else
@@ -1189,7 +1189,7 @@ else
[ -z "$ASSET" ] && ASSET=$(pick_mihomo_asset "MetaCubeX/mihomo" "$TAG" "$(map_mihomo_arch "$MODELTYPE")" "alpha")
[ -z "$ASSET" ] && ASSET=$(pick_mihomo_asset "MetaCubeX/mihomo" "$TAG" "$(map_mihomo_arch "$MODELTYPE")" "stable")
URL="https://github.com/MetaCubeX/mihomo/releases/download/${TAG}/${ASSET}"
TARGET="/usr/bin/mihomo"
TARGET="/usr/share/clashoo/bin/mihomo-alpha"
VERSION_FILE="/usr/share/clashoo/mihomo_version"
VERSION_VALUE="$(printf '%s\n' "$ASSET" | sed -n 's#^mihomo-.*-alpha-\([0-9a-fA-F]\{7,\}\)\.gz$#\1#p' | head -n 1)"
[ -z "$VERSION_VALUE" ] && VERSION_VALUE="$TAG"
+4 -2
View File
@@ -11,8 +11,10 @@ LUCI_DEPENDS:=+luci-base +luci-lib-jsonc +curl +bandix
PKG_MAINTAINER:=timsaya
PKG_VERSION:=0.12.12
PKG_RELEASE:=1
PKG_RELEASE:=3
# Rebuild language packages when a package revision changes without a PO commit.
PKG_PO_VERSION=$(if $(DUMP),x,$(strip $(call findrev)))-r$(PKG_RELEASE)
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
# call BuildPackage - OpenWrt buildroot signature
@@ -0,0 +1,227 @@
'use strict';
'require baseclass';
'require rpc';
'require ui';
'require poll';
'require request';
var callStatus = rpc.declare({ object: 'luci.bandix', method: 'getGeoipStatus', expect: {} });
var callManage = rpc.declare({ object: 'luci.bandix', method: 'manageGeoip', params: ['action', 'profile', 'enabled'], expect: {} });
function size(bytes) {
if (bytes == null) return '—';
if (bytes < 1024) return bytes + ' B';
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KiB';
return (bytes / 1048576).toFixed(1) + ' MiB';
}
function unwrap(reply) {
if (!reply || reply.status !== 'success' || !reply.data) throw new Error(reply && (reply.message || reply.error) || _('GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix.'));
return reply.data;
}
function localized(names) {
var language = (L.env.lang || document.documentElement.lang || 'en').replace(/_/g, '-');
var key = /^zh/i.test(language) ? 'zh-CN' : language.split('-')[0];
return names && (names[key] || names.en) || '';
}
function countryName(info) {
if (info.country_code && typeof Intl !== 'undefined' && Intl.DisplayNames) {
try { return new Intl.DisplayNames([(L.env.lang || 'en').replace(/_/g, '-')], { type: 'region' }).of(info.country_code); } catch (e) { /* use database names */ }
}
return localized(info.country_names) || info.country_code || '';
}
var scopes = {
local: _('Local network'), private: _('Private address'), loopback: _('Loopback'),
link_local: _('Link-local address'), shared: _('Shared address (CGNAT)'),
multicast: _('Multicast'), unspecified: _('Unspecified address'),
documentation: _('Documentation address'), reserved: _('Reserved address'), unknown: _('Unknown location')
};
var phases = {
preparing: _('Checking database version…'), checking_space: _('Checking storage…'),
downloading: _('Downloading database…'), verifying: _('Verifying database…'),
activating: _('Loading database…'), importing: _('Importing database…'),
completed: _('Database ready'), up_to_date: _('Database is up to date'),
cancelled: _('Download cancelled'), failed: _('Database operation failed')
};
return baseclass.extend({
describe: function (info) {
if (!info) return null;
if (info.scope !== 'public') return { summary: scopes[info.scope] || scopes.unknown, details: scopes[info.scope] || scopes.unknown };
var country = countryName(info), region = localized(info.region_names), city = localized(info.city_names);
var location = [country, region, city].filter(function (value, index, all) { return value && all.indexOf(value) === index; }).join(' · ');
return {
summary: [location, info.organization].filter(Boolean).join(' · ') || scopes.unknown,
details: [location, info.asn ? 'AS' + info.asn : '', info.organization].filter(Boolean).join('\n')
};
},
render: function () {
if (this._root) return this._root;
var root, current = null, pending = false, refreshing = false, dirtyProfile = false;
var badge = E('strong', {}, _('Loading…'));
var enabled = E('input', { type: 'checkbox', disabled: true });
var profile = E('select', { 'class': 'cbi-input-select', 'aria-label': _('Database contents') }, [
E('option', { value: 'country' }, _('Country/region — approximately 3.3 MiB')),
E('option', { value: 'country_asn' }, _('Country/region + network organization — approximately 12 MiB')),
E('option', { value: 'city_asn' }, _('Province/city + network organization — approximately 57 MiB'))
]);
var importedCity = null;
var details = E('div', { style: 'color:var(--text-color-secondary,#888);font-size:0.9em;line-height:1.6;overflow-wrap:anywhere' });
var message = E('div', { role: 'status', 'aria-live': 'polite', style: 'font-size:0.9em;overflow-wrap:anywhere' });
var progressFill = E('div', { style: 'width:0%' });
var progress = E('div', { 'class': 'cbi-progressbar', style: 'display:none;margin:8px 0', role: 'progressbar', 'aria-valuemin': 0, 'aria-valuemax': 100 }, progressFill);
var download = E('button', { type: 'button', 'class': 'btn cbi-button cbi-button-apply' }, _('Download and enable'));
var upload = E('button', { type: 'button', 'class': 'btn cbi-button' }, _('Upload database'));
var cancel = E('button', { type: 'button', 'class': 'btn cbi-button', style: 'display:none' }, _('Cancel'));
var remove = E('button', { type: 'button', 'class': 'btn cbi-button cbi-button-negative', style: 'display:none' }, _('Delete'));
function display(status) {
var wasBusy = current && current.job && current.job.busy;
if (wasBusy && status.job && !status.job.busy && status.job.phase === 'completed') dirtyProfile = false;
current = status;
var job = status.job || {}, databases = status.databases || [], busy = pending || job.busy;
badge.style.color = status.enabled ? 'var(--success-color,#2f9e44)' : '';
badge.textContent = status.enabled ? _('Enabled') : databases.length ? _('Disabled') : _('Not installed');
enabled.checked = !!status.enabled; enabled.disabled = busy || !databases.length;
if (!dirtyProfile && status.profile) {
if (status.profile === 'city' && !importedCity) {
importedCity = E('option', { value: 'city' }, _('Province/city (uploaded database)')); profile.appendChild(importedCity);
}
profile.value = status.profile;
}
if (job.busy && job.profile) profile.value = job.profile;
profile.disabled = busy;
download.disabled = busy; upload.disabled = busy;
download.textContent = databases.length ? _('Update database') : _('Download and enable');
remove.style.display = databases.length || status.load_error ? '' : 'none'; remove.disabled = busy;
cancel.style.display = job.busy && job.phase !== 'activating' ? '' : 'none'; cancel.disabled = pending;
var builds = databases.map(function (db) {
var name = { country: _('Country/region'), city: _('Province/city'), asn: _('Network organization') }[db.kind] || db.kind;
var date = '—';
if (db.build_epoch) {
try { date = new Date(db.build_epoch * 1000).toLocaleDateString((L.env.lang || 'en').replace(/_/g, '-')); }
catch (e) { date = new Date(db.build_epoch * 1000).toLocaleDateString(); }
}
return name + ' ' + date;
});
details.textContent = [
builds.length ? _('Version') + ': ' + builds.join(' · ') : '',
_('Storage used') + ': ' + size(status.installed_bytes) + ' · ' + _('Available space') + ': ' + size(status.free_bytes),
_('Database directory') + ': ' + status.directory
].filter(Boolean).join('\n'); details.style.whiteSpace = 'pre-line';
var total = job.total_bytes;
var percent = total > 0 ? Math.min(100, Math.floor((job.downloaded_bytes || 0) * 100 / total)) : null;
progress.style.display = job.busy && total > 0 ? '' : 'none';
progressFill.style.width = (percent || 0) + '%';
progress.title = percent == null ? '' : percent + '%';
if (percent != null) progress.setAttribute('aria-valuenow', percent);
message.style.color = job.phase === 'failed' || status.load_error ? 'var(--error-color,#c0392b)' : '';
if (status.load_error && !job.busy) {
message.textContent = _('The installed database could not be loaded. Download or upload it again.');
message.title = status.load_error;
} else if (job.phase === 'failed') {
var errorMessage = job.error_phase === 'checking_space'
? _('Cannot prepare storage. Check free space and directory permissions.')
: job.error_phase === 'verifying'
? _('Database validation failed. The previous database is unchanged.')
: _('Database operation failed. Retry or upload a local database.');
if (job.error_phase === 'checking_space' && status.free_bytes != null && job.required_bytes > status.free_bytes) {
errorMessage = _('Not enough free space for this database.') + ' ' + _('Required space') + ': ' + size(job.required_bytes) + ' · ' + _('Available space') + ': ' + size(status.free_bytes);
}
message.textContent = errorMessage; message.title = job.error || '';
} else {
message.textContent = (phases[job.phase] || '') + (job.busy && total > 0 ? ' ' + size(job.downloaded_bytes || 0) + ' / ' + size(total) + ' (' + percent + '%)' : '');
message.title = job.current_file || '';
}
}
function refresh() {
if (refreshing || (root && !root.isConnected)) return Promise.resolve();
refreshing = true;
return callStatus().then(unwrap).then(display).catch(function (error) {
message.textContent = _('GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix.');
message.title = error.message || String(error);
download.disabled = true; upload.disabled = true; enabled.disabled = true;
}).finally(function () { refreshing = false; });
}
function manage(action, selected, checked) {
pending = true; if (current) display(current);
return callManage(action, selected || '', checked ? '1' : '0').then(unwrap).then(function (status) {
if (action === 'download') dirtyProfile = true;
display(status);
}).catch(function (error) {
ui.addNotification(null, E('p', _('Database operation failed') + ': ' + (error.message || error)), 'error');
}).finally(function () { pending = false; if (current) display(current); });
}
profile.addEventListener('change', function () { dirtyProfile = true; });
enabled.addEventListener('change', function () { manage('enable', null, enabled.checked); });
download.addEventListener('click', function () { manage('download', profile.value); });
cancel.addEventListener('click', function () { manage('cancel'); });
remove.addEventListener('click', function () {
ui.showModal(_('Delete GeoIP databases'), [
E('p', _('Remove installed databases and disable IP location lookup?')),
E('div', { 'class': 'right' }, [
E('button', { type: 'button', 'class': 'btn', click: ui.hideModal }, _('Cancel')), ' ',
E('button', { type: 'button', 'class': 'btn cbi-button-negative', click: function () { ui.hideModal(); dirtyProfile = false; manage('delete'); } }, _('Delete'))
])
]);
});
upload.addEventListener('click', function () {
if (!current) return;
var limit = typeof current.upload_max_bytes === 'number' ? current.upload_max_bytes : 8 * 1048576;
var selection = E('input', { type: 'file', accept: '.mmdb', 'aria-label': _('Upload database') });
var uploadError = E('p', { style: 'color:var(--error-color,#c0392b)', role: 'alert' });
var uploadAction = E('button', { type: 'button', 'class': 'btn cbi-button-action important', disabled: true }, _('Upload and enable'));
selection.addEventListener('change', function () {
var file = selection.files[0];
uploadAction.disabled = !file || !/\.mmdb$/i.test(file.name) || file.size === 0 || file.size > limit;
uploadError.textContent = uploadAction.disabled && file ? _('Choose an uncompressed .mmdb file within the upload size limit.') : '';
});
uploadAction.addEventListener('click', function () {
var file = selection.files[0]; if (!file || uploadAction.disabled) return;
pending = true; display(current);
var fill = E('div', { style: 'width:0%' });
var bar = E('div', { 'class': 'cbi-progressbar' }, fill);
ui.showModal(_('Uploading database…'), [bar]);
var data = new FormData();
data.append('sessionid', rpc.getSessionID());
data.append('filename', '/tmp/bandix-geoip-upload.mmdb');
data.append('filedata', file);
request.post(L.env.cgi_base + '/cgi-upload', data, {
timeout: 0,
progress: function (event) {
if (!event.total) return;
var percent = Math.min(100, Math.round(event.loaded * 100 / event.total));
fill.style.width = percent + '%'; bar.title = percent + '%';
}
}).then(function (response) {
var reply = response.json();
if (!response.ok || reply.failure) throw new Error(reply.message || _('Database upload failed'));
ui.hideModal(); return manage('import');
}).catch(function (error) {
ui.hideModal(); ui.addNotification(null, E('p', _('Database upload failed') + ': ' + (error.message || error)), 'error');
}).finally(function () { pending = false; if (current) display(current); });
});
ui.showModal(_('Upload database'), [
E('p', {}, _('Maximum upload size') + ': ' + size(limit)), selection, uploadError,
E('div', { 'class': 'right' }, [E('button', { type: 'button', 'class': 'btn', click: ui.hideModal }, _('Cancel')), ' ', uploadAction])
]);
});
root = E('div', { style: 'max-width:780px' }, [
E('div', { style: 'display:flex;flex-wrap:wrap;align-items:center;gap:16px;margin-bottom:12px' }, [
E('label', { style: 'display:flex;align-items:center;gap:8px' }, [enabled, _('Enable IP location lookup')]), badge
]),
E('div', { style: 'display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:10px' }, [profile, download, upload, cancel, remove]),
details, progress, message,
E('div', { style: 'font-size:0.85em;opacity:0.75;margin-top:8px' }, [
_('Data source') + ': ', E('a', { href: 'https://github.com/P3TERX/GeoLite.mmdb', target: '_blank', rel: 'noopener noreferrer' }, 'P3TERX / MaxMind GeoLite2'),
' · ', E('a', { href: 'https://www.maxmind.com/en/geolite2/eula', target: '_blank', rel: 'noopener noreferrer' }, _('Data terms')),
E('div', {}, _('Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first.'))
])
]);
this._root = root;
poll.add(refresh, 2);
// renderWidget returns before LuCI attaches the form to the document.
setTimeout(refresh, 0);
return root;
}
});
@@ -4,6 +4,7 @@
'require uci';
'require rpc';
'require poll';
'require bandix.geoip as geoip';
var BANDIX_MODAL_BG_OPENWRT2020_LIGHT = '#ffffff';
var BANDIX_MODAL_BG_OPENWRT2020_DARK = '#2a2a2a';
@@ -136,15 +137,21 @@ function formatSize(bytes) {
// IPv6 地址按 RFC 3986 用方括号包起来,一是避免 '2600:...:8000::' + ':' + '80' 拼出
// ':::80' 这种分不清边界的写法,二是选中复制出来就是 [addr]:port,可以直接粘去用。
// 地址和端口是行内元素,复制时不会被拆成两行;端口自身 nowrap,不会被折断
function flowEndpointCell(addr, port) {
function flowEndpointCell(addr, port, information) {
var text = addr || '-';
if (text.indexOf(':') >= 0) {
text = '[' + text + ']';
}
return E('td', { 'class': 'flows-addr-cell' }, [
var description = geoip.describe(information);
var children = [E('div', {}, [
E('span', { 'class': 'flows-addr' }, text),
E('span', { 'class': 'flows-port' }, port ? ':' + port : '')
]);
])];
if (description) children.push(E('div', {
'class': 'flows-geoip', title: description.details,
style: 'font-size:0.8rem;opacity:0.75;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px'
}, description.summary));
return E('td', { 'class': 'flows-addr-cell' }, children);
}
function formatDeviceName(device) {
@@ -1211,7 +1218,8 @@ return view.extend({
total: res.data.total || 0,
page: res.data.page || currentPage,
page_size: res.data.page_size || currentPageSize,
total_pages: res.data.total_pages || 1
total_pages: res.data.total_pages || 1,
geoip: res.data.geoip || {}
};
}
@@ -1233,6 +1241,7 @@ return view.extend({
tableBody.innerHTML = '';
var normalized = normalizeFlowsResponse(res);
var flows = normalized.items;
var information = normalized.geoip || {};
totalItems = normalized.total;
currentPage = normalized.page;
totalPages = Math.max(1, normalized.total_pages);
@@ -1258,11 +1267,11 @@ return view.extend({
tableBody.appendChild(E('tr', {}, [
E('td', { 'class': protoCls }, (f.protocol || '-').toUpperCase()),
E('td', { 'class': 'flows-state-cell ' + stateCls }, f.state || '-'),
flowEndpointCell(f.orig && f.orig.src, f.orig && f.orig.sport),
flowEndpointCell(f.orig && f.orig.dst, f.orig && f.orig.dport),
flowEndpointCell(f.orig && f.orig.src, f.orig && f.orig.sport, information[f.orig && f.orig.src]),
flowEndpointCell(f.orig && f.orig.dst, f.orig && f.orig.dport, information[f.orig && f.orig.dst]),
E('td', {}, sendStr),
flowEndpointCell(f.repl && f.repl.src, f.repl && f.repl.sport),
flowEndpointCell(f.repl && f.repl.dst, f.repl && f.repl.dport),
flowEndpointCell(f.repl && f.repl.src, f.repl && f.repl.sport, information[f.repl && f.repl.src]),
flowEndpointCell(f.repl && f.repl.dst, f.repl && f.repl.dport, information[f.repl && f.repl.dst]),
E('td', {}, replyStr),
E('td', { 'style': 'font-size: 0.8rem;' }, flagsStr)
]));
@@ -4,6 +4,7 @@
'require ui';
'require uci';
'require rpc';
'require bandix.geoip as geoip';
'require tools.widgets as widgets';
@@ -231,6 +232,13 @@ return view.extend({
s.description = _('Configure basic parameters for Bandix service');
s.addremove = false;
o = s.option(form.Value, 'host', _('Listen Address'),
_('IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces.'));
o.default = '127.0.0.1';
o.datatype = 'ipaddr("nomask")';
o.placeholder = '127.0.0.1';
o.rmempty = false;
// 添加端口设置选项
o = s.option(form.Value, 'port', _('Port'),
_('Port for Bandix service to listen on'));
@@ -785,6 +793,16 @@ return view.extend({
o.default = '0';
o.rmempty = false;
o = s.option(form.DummyValue, '_geoip_manager', _('IP location database'));
o.renderWidget = function () { return geoip.render(); };
o = s.option(form.Value, 'geoip_dir', _('Database directory'),
_('Use persistent storage or an external drive. Save and apply directory changes before downloading.'));
o.default = '/usr/share/bandix-geoip';
o.placeholder = '/usr/share/bandix-geoip';
o.datatype = 'directory';
o.rmempty = false;
// 4. DNS监控设置部分 (dns)
s = m.section(form.NamedSection, 'dns', 'dns', _('DNS Monitor Settings'));
s.description = _('Configure DNS monitoring related parameters');
+189 -30
View File
@@ -221,12 +221,6 @@ msgstr "WAN cargado"
msgid "WAN Downloaded"
msgstr "WAN descargado"
msgid "Total Upload"
msgstr "Carga total"
msgid "Total Download"
msgstr "Descarga total"
msgid "LAN Upload"
msgstr "Carga LAN"
@@ -422,18 +416,12 @@ msgstr "Página"
msgid "of"
msgstr "de"
msgid "Total"
msgstr "Total"
msgid "records"
msgstr "registros"
msgid "Per Page"
msgstr "Por página"
msgid ""
msgstr ""
msgid "Total Queries"
msgstr "Total de consultas"
@@ -938,18 +926,6 @@ msgstr "Máximo"
msgid "Minimum"
msgstr "Mínimo"
msgid "WAN Upload"
msgstr "Subida WAN"
msgid "WAN Download"
msgstr "Descarga WAN"
msgid "WAN Uploaded"
msgstr "Subido WAN"
msgid "WAN Downloaded"
msgstr "Descargado WAN"
msgid "Clear Traffic Data"
msgstr "Borrar datos de tráfico"
@@ -1082,9 +1058,6 @@ msgstr "Descargar e Instalar"
msgid "Manual Download"
msgstr "Descarga Manual"
msgid "Close"
msgstr "Cerrar"
msgid "Starting installation... The page will refresh automatically in 30 seconds."
msgstr "Iniciando instalación... La página se actualizará automáticamente en 30 segundos."
@@ -1094,9 +1067,6 @@ msgstr "Por favor, borre manualmente la caché del navegador después de actuali
msgid "Traffic Statistics"
msgstr "Estadísticas de Tráfico"
msgid "Traffic Statistics"
msgstr "Estadísticas de Tráfico"
msgid "Device Usage Ranking"
msgstr "Clasificación de Uso de Dispositivos"
@@ -1351,3 +1321,192 @@ msgstr "No disponible"
msgid "Show reply direction"
msgstr "Mostrar la dirección de respuesta"
msgid "Available space"
msgstr "Espacio disponible"
msgid "Cannot prepare storage. Check free space and directory permissions."
msgstr "No se pudo preparar el almacenamiento. Compruebe el espacio y los permisos."
msgid "Checking database version…"
msgstr "Comprobando la versión…"
msgid "Checking storage…"
msgstr "Comprobando el almacenamiento…"
msgid "Choose an uncompressed .mmdb file within the upload size limit."
msgstr "Seleccione un archivo .mmdb sin comprimir dentro del límite de tamaño."
msgid "Country/region + network organization — approximately 12 MiB"
msgstr "País/región + organización de red · unos 12 MiB"
msgid "Country/region — approximately 3.3 MiB"
msgstr "País/región · unos 3,3 MiB"
msgid "Data source"
msgstr "Fuente de datos"
msgid "Data terms"
msgstr "Condiciones de uso"
msgid "Database contents"
msgstr "Contenido de la base"
msgid "Database directory"
msgstr "Directorio de la base"
msgid "Database enabled"
msgstr "Base de datos activada"
msgid "Database is up to date"
msgstr "La base está actualizada"
msgid "Database operation failed"
msgstr "Error en la operación de la base"
msgid "Database operation failed. Retry or upload a local database."
msgstr "Error en la operación. Reintente o cargue una base local."
msgid "Database upload failed"
msgstr "Error al cargar la base"
msgid "Database validation failed. The previous database is unchanged."
msgstr "Error de validación. Se conserva la base anterior."
msgid "Delete"
msgstr "Eliminar"
msgid "Delete GeoIP databases"
msgstr "Eliminar bases GeoIP"
msgid "Disabled"
msgstr "Desactivado"
msgid "Documentation address"
msgstr "Dirección de documentación"
msgid "Download and enable"
msgstr "Descargar y activar"
msgid "Download cancelled"
msgstr "Descarga cancelada"
msgid "Downloading database…"
msgstr "Descargando la base…"
msgid "Enable IP location lookup"
msgstr "Activar ubicación de IP"
msgid "Enabled"
msgstr "Activado"
msgid "GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix."
msgstr "GeoIP no está disponible. Active la monitorización de conexiones y aplique los ajustes, o actualice Bandix."
msgid "IP location database"
msgstr "Base de ubicación de IP"
msgid "Importing database…"
msgstr "Importando la base…"
msgid "Link-local address"
msgstr "Dirección de enlace local"
msgid "Loading database…"
msgstr "Cargando la base…"
msgid "Local network"
msgstr "Red local"
msgid "Loopback"
msgstr "Bucle local"
msgid "Maximum upload size"
msgstr "Tamaño máximo de carga"
msgid "Multicast"
msgstr "Multidifusión"
msgid "Not installed"
msgstr "Sin instalar"
msgid "Private address"
msgstr "Dirección privada"
msgid "Province/city (uploaded database)"
msgstr "Provincia/ciudad (base cargada)"
msgid "Province/city + network organization — approximately 57 MiB"
msgstr "Provincia/ciudad + organización de red · unos 57 MiB"
msgid "Remove installed databases and disable IP location lookup?"
msgstr "¿Eliminar las bases y desactivar la ubicación de IP?"
msgid "Reserved address"
msgstr "Dirección reservada"
msgid "Shared address (CGNAT)"
msgstr "Dirección compartida (CGNAT)"
msgid "Storage used"
msgstr "Espacio utilizado"
msgid "The installed database could not be loaded. Download or upload it again."
msgstr "No se pudo cargar la base. Descárguela o cárguela de nuevo."
msgid "Unknown"
msgstr "Desconocido"
msgid "Unknown location"
msgstr "Ubicación desconocida"
msgid "Unspecified address"
msgstr "Dirección sin especificar"
msgid "Update database"
msgstr "Actualizar base"
msgid "Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first."
msgstr "Cargue un archivo Country, City o ASN .mmdb sin comprimir. Instale Country o City antes de añadir ASN."
msgid "Upload and enable"
msgstr "Cargar y activar"
msgid "Upload database"
msgstr "Cargar base"
msgid "Uploading database…"
msgstr "Subiendo la base…"
msgid "Use persistent storage or an external drive. Save and apply directory changes before downloading."
msgstr "Use almacenamiento persistente o externo. Guarde y aplique los cambios de directorio antes de descargar."
msgid "Verifying database…"
msgstr "Verificando la base…"
msgid "Version"
msgstr "Versión"
msgid "Country/region"
msgstr "País/región"
msgid "Province/city"
msgstr "Provincia/ciudad"
msgid "Network organization"
msgstr "Organización de red"
msgid "Not enough free space for this database."
msgstr "No hay espacio suficiente para esta base."
msgid "Required space"
msgstr "Espacio necesario"
msgid "Database ready"
msgstr "Base lista"
msgid "Listen Address"
msgstr "Dirección de escucha"
msgid "IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces."
msgstr "Dirección IP de escucha de Bandix. Use 127.0.0.1 para acceso local o 0.0.0.0 / :: para todas las interfaces."
+189 -30
View File
@@ -221,12 +221,6 @@ msgstr "WAN envoyé"
msgid "WAN Downloaded"
msgstr "WAN téléchargé"
msgid "Total Upload"
msgstr "Téléversement total"
msgid "Total Download"
msgstr "Téléchargement total"
msgid "LAN Upload"
msgstr "Débit envoi LAN"
@@ -422,18 +416,12 @@ msgstr "Page"
msgid "of"
msgstr "sur"
msgid "Total"
msgstr "Total"
msgid "records"
msgstr "enregistrements"
msgid "Per Page"
msgstr "Par page"
msgid ""
msgstr ""
msgid "Total Queries"
msgstr "Total des requêtes"
@@ -938,18 +926,6 @@ msgstr "Maximum"
msgid "Minimum"
msgstr "Minimum"
msgid "WAN Upload"
msgstr "Envoi WAN"
msgid "WAN Download"
msgstr "Téléchargement WAN"
msgid "WAN Uploaded"
msgstr "Envoyé WAN"
msgid "WAN Downloaded"
msgstr "Téléchargé WAN"
msgid "Clear Traffic Data"
msgstr "Effacer les données de trafic"
@@ -1082,9 +1058,6 @@ msgstr "Télécharger et Installer"
msgid "Manual Download"
msgstr "Téléchargement Manuel"
msgid "Close"
msgstr "Fermer"
msgid "Starting installation... The page will refresh automatically in 30 seconds."
msgstr "Démarrage de l'installation... La page sera actualisée automatiquement dans 30 secondes."
@@ -1094,9 +1067,6 @@ msgstr "Veuillez vider manuellement le cache du navigateur après la mise à jou
msgid "Traffic Statistics"
msgstr "Statistiques de Trafic"
msgid "Traffic Statistics"
msgstr "Statistiques de Trafic"
msgid "Device Usage Ranking"
msgstr "Classement d'Utilisation des Appareils"
@@ -1351,3 +1321,192 @@ msgstr "Indisponible"
msgid "Show reply direction"
msgstr "Afficher la direction de réponse"
msgid "Available space"
msgstr "Espace disponible"
msgid "Cannot prepare storage. Check free space and directory permissions."
msgstr "Impossible de préparer le stockage. Vérifiez l’espace libre et les permissions."
msgid "Checking database version…"
msgstr "Vérification de la version…"
msgid "Checking storage…"
msgstr "Vérification du stockage…"
msgid "Choose an uncompressed .mmdb file within the upload size limit."
msgstr "Choisissez un fichier .mmdb non compressé respectant la taille limite."
msgid "Country/region + network organization — approximately 12 MiB"
msgstr "Pays/région + organisation réseau · environ 12 MiB"
msgid "Country/region — approximately 3.3 MiB"
msgstr "Pays/région · environ 3,3 MiB"
msgid "Data source"
msgstr "Source des données"
msgid "Data terms"
msgstr "Conditions d’utilisation"
msgid "Database contents"
msgstr "Contenu de la base"
msgid "Database directory"
msgstr "Répertoire de la base"
msgid "Database enabled"
msgstr "Base activée"
msgid "Database is up to date"
msgstr "La base est à jour"
msgid "Database operation failed"
msgstr "Échec de l’opération"
msgid "Database operation failed. Retry or upload a local database."
msgstr "Échec de l’opération. Réessayez ou importez une base locale."
msgid "Database upload failed"
msgstr "Échec de l’envoi de la base"
msgid "Database validation failed. The previous database is unchanged."
msgstr "Échec de validation. La base précédente est conservée."
msgid "Delete"
msgstr "Supprimer"
msgid "Delete GeoIP databases"
msgstr "Supprimer les bases GeoIP"
msgid "Disabled"
msgstr "Désactivé"
msgid "Documentation address"
msgstr "Adresse de documentation"
msgid "Download and enable"
msgstr "Télécharger et activer"
msgid "Download cancelled"
msgstr "Téléchargement annulé"
msgid "Downloading database…"
msgstr "Téléchargement de la base…"
msgid "Enable IP location lookup"
msgstr "Activer la géolocalisation IP"
msgid "Enabled"
msgstr "Activé"
msgid "GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix."
msgstr "GeoIP indisponible. Activez le suivi des connexions et appliquez les paramètres, ou mettez Bandix à jour."
msgid "IP location database"
msgstr "Base de géolocalisation IP"
msgid "Importing database…"
msgstr "Importation de la base…"
msgid "Link-local address"
msgstr "Adresse de lien local"
msgid "Loading database…"
msgstr "Chargement de la base…"
msgid "Local network"
msgstr "Réseau local"
msgid "Loopback"
msgstr "Bouclage"
msgid "Maximum upload size"
msgstr "Taille maximale d’envoi"
msgid "Multicast"
msgstr "Multidiffusion"
msgid "Not installed"
msgstr "Non installé"
msgid "Private address"
msgstr "Adresse privée"
msgid "Province/city (uploaded database)"
msgstr "Région/ville (base importée)"
msgid "Province/city + network organization — approximately 57 MiB"
msgstr "Région/ville + organisation réseau · environ 57 MiB"
msgid "Remove installed databases and disable IP location lookup?"
msgstr "Supprimer les bases et désactiver la géolocalisation IP ?"
msgid "Reserved address"
msgstr "Adresse réservée"
msgid "Shared address (CGNAT)"
msgstr "Adresse partagée (CGNAT)"
msgid "Storage used"
msgstr "Espace utilisé"
msgid "The installed database could not be loaded. Download or upload it again."
msgstr "Impossible de charger la base. Téléchargez-la ou importez-la à nouveau."
msgid "Unknown"
msgstr "Inconnu"
msgid "Unknown location"
msgstr "Localisation inconnue"
msgid "Unspecified address"
msgstr "Adresse non spécifiée"
msgid "Update database"
msgstr "Mettre à jour la base"
msgid "Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first."
msgstr "Importez un fichier Country, City ou ASN .mmdb non compressé. Installez Country ou City avant d’ajouter ASN."
msgid "Upload and enable"
msgstr "Importer et activer"
msgid "Upload database"
msgstr "Importer une base"
msgid "Uploading database…"
msgstr "Envoi de la base…"
msgid "Use persistent storage or an external drive. Save and apply directory changes before downloading."
msgstr "Utilisez un stockage persistant ou externe. Enregistrez et appliquez le changement de répertoire avant de télécharger."
msgid "Verifying database…"
msgstr "Vérification de la base…"
msgid "Version"
msgstr "Version"
msgid "Country/region"
msgstr "Pays/région"
msgid "Province/city"
msgstr "Région/ville"
msgid "Network organization"
msgstr "Organisation réseau"
msgid "Not enough free space for this database."
msgstr "Espace insuffisant pour cette base."
msgid "Required space"
msgstr "Espace nécessaire"
msgid "Database ready"
msgstr "Base prête"
msgid "Listen Address"
msgstr "Adresse d’écoute"
msgid "IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces."
msgstr "Adresse IP d’écoute de Bandix. Utilisez 127.0.0.1 pour un accès local ou 0.0.0.0 / :: pour toutes les interfaces."
+189 -30
View File
@@ -221,12 +221,6 @@ msgstr "WAN アップロード済み"
msgid "WAN Downloaded"
msgstr "WAN ダウンロード済み"
msgid "Total Upload"
msgstr "総アップロード速度"
msgid "Total Download"
msgstr "総ダウンロード速度"
msgid "LAN Upload"
msgstr "LAN アップロード速度"
@@ -422,18 +416,12 @@ msgstr "ページ"
msgid "of"
msgstr "の"
msgid "Total"
msgstr "合計"
msgid "records"
msgstr "件の記録"
msgid "Per Page"
msgstr "ページあたり"
msgid ""
msgstr "件"
msgid "Total Queries"
msgstr "総クエリ数"
@@ -938,18 +926,6 @@ msgstr "最大"
msgid "Minimum"
msgstr "最小"
msgid "WAN Upload"
msgstr "WAN アップロード"
msgid "WAN Download"
msgstr "WAN ダウンロード"
msgid "WAN Uploaded"
msgstr "WAN アップロード量"
msgid "WAN Downloaded"
msgstr "WAN ダウンロード量"
msgid "Clear Traffic Data"
msgstr "トラフィックデータを削除"
@@ -1082,9 +1058,6 @@ msgstr "ダウンロードしてインストール"
msgid "Manual Download"
msgstr "手動ダウンロード"
msgid "Close"
msgstr "閉じる"
msgid "Starting installation... The page will refresh automatically in 30 seconds."
msgstr "インストールを開始しています... ページは30秒後に自動的に更新されます。"
@@ -1094,9 +1067,6 @@ msgstr "更新後、ブラウザのキャッシュを手動でクリアしてく
msgid "Traffic Statistics"
msgstr "トラフィック統計"
msgid "Traffic Statistics"
msgstr "トラフィック統計"
msgid "Device Usage Ranking"
msgstr "デバイス使用量ランキング"
@@ -1351,3 +1321,192 @@ msgstr "利用不可"
msgid "Show reply direction"
msgstr "応答方向を表示"
msgid "Available space"
msgstr "空き容量"
msgid "Cannot prepare storage. Check free space and directory permissions."
msgstr "保存先を準備できません。空き容量と権限を確認してください。"
msgid "Checking database version…"
msgstr "データベースのバージョンを確認中…"
msgid "Checking storage…"
msgstr "空き容量を確認中…"
msgid "Choose an uncompressed .mmdb file within the upload size limit."
msgstr "上限サイズ以内の未圧縮 .mmdb ファイルを選択してください。"
msgid "Country/region + network organization — approximately 12 MiB"
msgstr "国・地域 + ネットワーク組織 · 約 12 MiB"
msgid "Country/region — approximately 3.3 MiB"
msgstr "国・地域 · 約 3.3 MiB"
msgid "Data source"
msgstr "データ提供元"
msgid "Data terms"
msgstr "データ利用規約"
msgid "Database contents"
msgstr "データベースの内容"
msgid "Database directory"
msgstr "データベース保存先"
msgid "Database enabled"
msgstr "データベースを有効にしました"
msgid "Database is up to date"
msgstr "データベースは最新です"
msgid "Database operation failed"
msgstr "データベース操作に失敗しました"
msgid "Database operation failed. Retry or upload a local database."
msgstr "操作に失敗しました。再試行するかローカルのデータベースをアップロードしてください。"
msgid "Database upload failed"
msgstr "データベースのアップロードに失敗しました"
msgid "Database validation failed. The previous database is unchanged."
msgstr "検証に失敗しました。既存のデータベースは保持されています。"
msgid "Delete"
msgstr "削除"
msgid "Delete GeoIP databases"
msgstr "GeoIP データベースを削除"
msgid "Disabled"
msgstr "無効"
msgid "Documentation address"
msgstr "文書用アドレス"
msgid "Download and enable"
msgstr "ダウンロードして有効化"
msgid "Download cancelled"
msgstr "ダウンロードを中止しました"
msgid "Downloading database…"
msgstr "データベースをダウンロード中…"
msgid "Enable IP location lookup"
msgstr "IP 位置情報の検索を有効化"
msgid "Enabled"
msgstr "有効"
msgid "GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix."
msgstr "GeoIP を利用できません。接続監視を有効にして設定を適用するか、Bandix を更新してください。"
msgid "IP location database"
msgstr "IP 位置情報データベース"
msgid "Importing database…"
msgstr "データベースをインポート中…"
msgid "Link-local address"
msgstr "リンクローカルアドレス"
msgid "Loading database…"
msgstr "データベースを読み込み中…"
msgid "Local network"
msgstr "ローカルネットワーク"
msgid "Loopback"
msgstr "ループバック"
msgid "Maximum upload size"
msgstr "最大アップロードサイズ"
msgid "Multicast"
msgstr "マルチキャスト"
msgid "Not installed"
msgstr "未インストール"
msgid "Private address"
msgstr "プライベートアドレス"
msgid "Province/city (uploaded database)"
msgstr "都道府県・都市(アップロード済み)"
msgid "Province/city + network organization — approximately 57 MiB"
msgstr "都道府県・都市 + ネットワーク組織 · 約 57 MiB"
msgid "Remove installed databases and disable IP location lookup?"
msgstr "データベースを削除し、IP 位置情報の検索を無効にしますか?"
msgid "Reserved address"
msgstr "予約済みアドレス"
msgid "Shared address (CGNAT)"
msgstr "共有アドレス(CGNAT)"
msgid "Storage used"
msgstr "使用容量"
msgid "The installed database could not be loaded. Download or upload it again."
msgstr "データベースを読み込めません。再度ダウンロードまたはアップロードしてください。"
msgid "Unknown"
msgstr "不明"
msgid "Unknown location"
msgstr "位置情報不明"
msgid "Unspecified address"
msgstr "未指定アドレス"
msgid "Update database"
msgstr "データベースを更新"
msgid "Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first."
msgstr "未圧縮の Country、City、ASN の .mmdb ファイルをアップロードできます。ASN の追加前に Country または City をインストールしてください。"
msgid "Upload and enable"
msgstr "アップロードして有効化"
msgid "Upload database"
msgstr "データベースをアップロード"
msgid "Uploading database…"
msgstr "データベースをアップロード中…"
msgid "Use persistent storage or an external drive. Save and apply directory changes before downloading."
msgstr "永続ストレージまたは外付けドライブを使用してください。保存先の変更を保存・適用してからダウンロードしてください。"
msgid "Verifying database…"
msgstr "データベースを検証中…"
msgid "Version"
msgstr "バージョン"
msgid "Country/region"
msgstr "国・地域"
msgid "Province/city"
msgstr "都道府県・都市"
msgid "Network organization"
msgstr "ネットワーク組織"
msgid "Not enough free space for this database."
msgstr "このデータベースを保存する空き容量が不足しています。"
msgid "Required space"
msgstr "必要な容量"
msgid "Database ready"
msgstr "データベースの準備完了"
msgid "Listen Address"
msgstr "待ち受けアドレス"
msgid "IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces."
msgstr "Bandix が待ち受ける IP アドレス。ローカルアクセスには 127.0.0.1、すべてのインターフェースには 0.0.0.0 / :: を指定します。"
+189 -30
View File
@@ -221,12 +221,6 @@ msgstr "WAN wysłane"
msgid "WAN Downloaded"
msgstr "WAN pobrane"
msgid "Total Upload"
msgstr "Całkowite wysyłanie"
msgid "Total Download"
msgstr "Całkowite pobieranie"
msgid "LAN Upload"
msgstr "Wysyłanie LAN"
@@ -422,18 +416,12 @@ msgstr "Strona"
msgid "of"
msgstr "z"
msgid "Total"
msgstr "Całkowity"
msgid "records"
msgstr "rekordów"
msgid "Per Page"
msgstr "Na stronę"
msgid ""
msgstr ""
msgid "Total Queries"
msgstr "Całkowite zapytania"
@@ -938,18 +926,6 @@ msgstr "Maksimum"
msgid "Minimum"
msgstr "Minimum"
msgid "WAN Upload"
msgstr "Wysyłanie WAN"
msgid "WAN Download"
msgstr "Pobieranie WAN"
msgid "WAN Uploaded"
msgstr "Wysłano WAN"
msgid "WAN Downloaded"
msgstr "Pobrano WAN"
msgid "Clear Traffic Data"
msgstr "Wyczyść dane ruchu"
@@ -1082,9 +1058,6 @@ msgstr "Pobierz i Zainstaluj"
msgid "Manual Download"
msgstr "Pobieranie Ręczne"
msgid "Close"
msgstr "Zamknij"
msgid "Starting installation... The page will refresh automatically in 30 seconds."
msgstr "Rozpoczynanie instalacji... Strona odświeży się automatycznie za 30 sekund."
@@ -1094,9 +1067,6 @@ msgstr "Po aktualizacji należy ręcznie wyczyścić pamięć podręczną przegl
msgid "Traffic Statistics"
msgstr "Statystyki ruchu"
msgid "Traffic Statistics"
msgstr "Statystyki ruchu"
msgid "Device Usage Ranking"
msgstr "Ranking Użycia Urządzeń"
@@ -1351,3 +1321,192 @@ msgstr "Niedostępne"
msgid "Show reply direction"
msgstr "Pokaż kierunek odpowiedzi"
msgid "Available space"
msgstr "Wolne miejsce"
msgid "Cannot prepare storage. Check free space and directory permissions."
msgstr "Nie można przygotować pamięci. Sprawdź wolne miejsce i uprawnienia katalogu."
msgid "Checking database version…"
msgstr "Sprawdzanie wersji bazy…"
msgid "Checking storage…"
msgstr "Sprawdzanie pamięci…"
msgid "Choose an uncompressed .mmdb file within the upload size limit."
msgstr "Wybierz nieskompresowany plik .mmdb mieszczący się w limicie rozmiaru."
msgid "Country/region + network organization — approximately 12 MiB"
msgstr "Kraj/region + organizacja sieciowa · ok. 12 MiB"
msgid "Country/region — approximately 3.3 MiB"
msgstr "Kraj/region · ok. 3,3 MiB"
msgid "Data source"
msgstr "Źródło danych"
msgid "Data terms"
msgstr "Warunki korzystania"
msgid "Database contents"
msgstr "Zawartość bazy"
msgid "Database directory"
msgstr "Katalog bazy"
msgid "Database enabled"
msgstr "Baza danych włączona"
msgid "Database is up to date"
msgstr "Baza danych jest aktualna"
msgid "Database operation failed"
msgstr "Operacja na bazie nie powiodła się"
msgid "Database operation failed. Retry or upload a local database."
msgstr "Operacja nie powiodła się. Spróbuj ponownie lub prześlij lokalną bazę."
msgid "Database upload failed"
msgstr "Przesyłanie bazy nie powiodło się"
msgid "Database validation failed. The previous database is unchanged."
msgstr "Weryfikacja nie powiodła się. Poprzednia baza pozostaje bez zmian."
msgid "Delete"
msgstr "Usuń"
msgid "Delete GeoIP databases"
msgstr "Usuń bazy GeoIP"
msgid "Disabled"
msgstr "Wyłączone"
msgid "Documentation address"
msgstr "Adres dokumentacyjny"
msgid "Download and enable"
msgstr "Pobierz i włącz"
msgid "Download cancelled"
msgstr "Pobieranie anulowane"
msgid "Downloading database…"
msgstr "Pobieranie bazy…"
msgid "Enable IP location lookup"
msgstr "Włącz geolokalizację IP"
msgid "Enabled"
msgstr "Włączone"
msgid "GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix."
msgstr "GeoIP jest niedostępne. Włącz monitorowanie połączeń i zastosuj ustawienia lub zaktualizuj Bandix."
msgid "IP location database"
msgstr "Baza geolokalizacji IP"
msgid "Importing database…"
msgstr "Importowanie bazy…"
msgid "Link-local address"
msgstr "Adres lokalny łącza"
msgid "Loading database…"
msgstr "Wczytywanie bazy…"
msgid "Local network"
msgstr "Sieć lokalna"
msgid "Loopback"
msgstr "Pętla zwrotna"
msgid "Maximum upload size"
msgstr "Maksymalny rozmiar pliku"
msgid "Multicast"
msgstr "Multicast"
msgid "Not installed"
msgstr "Niezainstalowane"
msgid "Private address"
msgstr "Adres prywatny"
msgid "Province/city (uploaded database)"
msgstr "Region/miasto (przesłana baza)"
msgid "Province/city + network organization — approximately 57 MiB"
msgstr "Region/miasto + organizacja sieciowa · ok. 57 MiB"
msgid "Remove installed databases and disable IP location lookup?"
msgstr "Usunąć bazy i wyłączyć geolokalizację IP?"
msgid "Reserved address"
msgstr "Adres zarezerwowany"
msgid "Shared address (CGNAT)"
msgstr "Adres współdzielony (CGNAT)"
msgid "Storage used"
msgstr "Zajęte miejsce"
msgid "The installed database could not be loaded. Download or upload it again."
msgstr "Nie można wczytać bazy. Pobierz lub prześlij ją ponownie."
msgid "Unknown"
msgstr "Nieznane"
msgid "Unknown location"
msgstr "Nieznana lokalizacja"
msgid "Unspecified address"
msgstr "Adres nieokreślony"
msgid "Update database"
msgstr "Aktualizuj bazę"
msgid "Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first."
msgstr "Prześlij nieskompresowany plik Country, City lub ASN .mmdb. Przed ASN zainstaluj Country lub City."
msgid "Upload and enable"
msgstr "Prześlij i włącz"
msgid "Upload database"
msgstr "Prześlij bazę"
msgid "Uploading database…"
msgstr "Przesyłanie bazy…"
msgid "Use persistent storage or an external drive. Save and apply directory changes before downloading."
msgstr "Użyj pamięci trwałej lub dysku zewnętrznego. Zapisz i zastosuj zmianę katalogu przed pobieraniem."
msgid "Verifying database…"
msgstr "Weryfikacja bazy…"
msgid "Version"
msgstr "Wersja"
msgid "Country/region"
msgstr "Kraj/region"
msgid "Province/city"
msgstr "Region/miasto"
msgid "Network organization"
msgstr "Organizacja sieciowa"
msgid "Not enough free space for this database."
msgstr "Brak miejsca na tę bazę danych."
msgid "Required space"
msgstr "Wymagane miejsce"
msgid "Database ready"
msgstr "Baza gotowa"
msgid "Listen Address"
msgstr "Adres nasłuchiwania"
msgid "IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces."
msgstr "Adres IP nasłuchiwania Bandix. Użyj 127.0.0.1 dla dostępu lokalnego lub 0.0.0.0 / :: dla wszystkich interfejsów."
+189 -30
View File
@@ -221,12 +221,6 @@ msgstr "WAN отправлено"
msgid "WAN Downloaded"
msgstr "WAN загружено"
msgid "Total Upload"
msgstr "Всего выгружено"
msgid "Total Download"
msgstr "Всего загружено"
msgid "LAN Upload"
msgstr "Скорость отправки LAN"
@@ -422,18 +416,12 @@ msgstr "Страница"
msgid "of"
msgstr "из"
msgid "Total"
msgstr "Всего"
msgid "records"
msgstr "записей"
msgid "Per Page"
msgstr "На странице"
msgid ""
msgstr ""
msgid "Total Queries"
msgstr "Всего запросов"
@@ -938,18 +926,6 @@ msgstr "Максимум"
msgid "Minimum"
msgstr "Минимум"
msgid "WAN Upload"
msgstr "Отправка WAN"
msgid "WAN Download"
msgstr "Загрузка WAN"
msgid "WAN Uploaded"
msgstr "Отправлено WAN"
msgid "WAN Downloaded"
msgstr "Загружено WAN"
msgid "Clear Traffic Data"
msgstr "Очистить данные трафика"
@@ -1082,9 +1058,6 @@ msgstr "Скачать и Установить"
msgid "Manual Download"
msgstr "Ручная Загрузка"
msgid "Close"
msgstr "Закрыть"
msgid "Starting installation... The page will refresh automatically in 30 seconds."
msgstr "Начало установки... Страница автоматически обновится через 30 секунд."
@@ -1094,9 +1067,6 @@ msgstr "Пожалуйста, вручную очистите кеш брауз
msgid "Traffic Statistics"
msgstr "Статистика трафика"
msgid "Traffic Statistics"
msgstr "Статистика трафика"
msgid "Device Usage Ranking"
msgstr "Рейтинг использования устройств"
@@ -1351,3 +1321,192 @@ msgstr "Недоступно"
msgid "Show reply direction"
msgstr "Показывать обратное направление"
msgid "Available space"
msgstr "Свободное место"
msgid "Cannot prepare storage. Check free space and directory permissions."
msgstr "Не удалось подготовить хранилище. Проверьте свободное место и права доступа."
msgid "Checking database version…"
msgstr "Проверка версии базы…"
msgid "Checking storage…"
msgstr "Проверка хранилища…"
msgid "Choose an uncompressed .mmdb file within the upload size limit."
msgstr "Выберите несжатый файл .mmdb, не превышающий ограничение размера."
msgid "Country/region + network organization — approximately 12 MiB"
msgstr "Страна/регион + сетевая организация · около 12 MiB"
msgid "Country/region — approximately 3.3 MiB"
msgstr "Страна/регион · около 3,3 MiB"
msgid "Data source"
msgstr "Источник данных"
msgid "Data terms"
msgstr "Условия использования"
msgid "Database contents"
msgstr "Содержимое базы"
msgid "Database directory"
msgstr "Каталог базы"
msgid "Database enabled"
msgstr "База данных включена"
msgid "Database is up to date"
msgstr "База данных актуальна"
msgid "Database operation failed"
msgstr "Ошибка операции с базой"
msgid "Database operation failed. Retry or upload a local database."
msgstr "Операция не удалась. Повторите попытку или загрузите локальную базу."
msgid "Database upload failed"
msgstr "Не удалось загрузить базу"
msgid "Database validation failed. The previous database is unchanged."
msgstr "Проверка не пройдена. Предыдущая база сохранена."
msgid "Delete"
msgstr "Удалить"
msgid "Delete GeoIP databases"
msgstr "Удалить базы GeoIP"
msgid "Disabled"
msgstr "Отключено"
msgid "Documentation address"
msgstr "Адрес для документации"
msgid "Download and enable"
msgstr "Скачать и включить"
msgid "Download cancelled"
msgstr "Загрузка отменена"
msgid "Downloading database…"
msgstr "Скачивание базы…"
msgid "Enable IP location lookup"
msgstr "Включить геолокацию IP"
msgid "Enabled"
msgstr "Включено"
msgid "GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix."
msgstr "GeoIP недоступен. Включите мониторинг соединений и примените настройки либо обновите Bandix."
msgid "IP location database"
msgstr "База геолокации IP"
msgid "Importing database…"
msgstr "Импорт базы…"
msgid "Link-local address"
msgstr "Локальный адрес канала"
msgid "Loading database…"
msgstr "Подключение базы…"
msgid "Local network"
msgstr "Локальная сеть"
msgid "Loopback"
msgstr "Петлевой адрес"
msgid "Maximum upload size"
msgstr "Максимальный размер загрузки"
msgid "Multicast"
msgstr "Многоадресная рассылка"
msgid "Not installed"
msgstr "Не установлено"
msgid "Private address"
msgstr "Частный адрес"
msgid "Province/city (uploaded database)"
msgstr "Регион/город (загруженная база)"
msgid "Province/city + network organization — approximately 57 MiB"
msgstr "Регион/город + сетевая организация · около 57 MiB"
msgid "Remove installed databases and disable IP location lookup?"
msgstr "Удалить базы и отключить геолокацию IP?"
msgid "Reserved address"
msgstr "Зарезервированный адрес"
msgid "Shared address (CGNAT)"
msgstr "Общий адрес (CGNAT)"
msgid "Storage used"
msgstr "Занято места"
msgid "The installed database could not be loaded. Download or upload it again."
msgstr "Не удалось открыть базу. Скачайте или загрузите её повторно."
msgid "Unknown"
msgstr "Неизвестно"
msgid "Unknown location"
msgstr "Местоположение неизвестно"
msgid "Unspecified address"
msgstr "Неуказанный адрес"
msgid "Update database"
msgstr "Обновить базу"
msgid "Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first."
msgstr "Можно загрузить несжатый файл Country, City или ASN .mmdb. Перед ASN установите Country или City."
msgid "Upload and enable"
msgstr "Загрузить и включить"
msgid "Upload database"
msgstr "Загрузить базу"
msgid "Uploading database…"
msgstr "Загрузка базы…"
msgid "Use persistent storage or an external drive. Save and apply directory changes before downloading."
msgstr "Используйте постоянное хранилище или внешний диск. Перед скачиванием сохраните и примените изменение каталога."
msgid "Verifying database…"
msgstr "Проверка базы…"
msgid "Version"
msgstr "Версия"
msgid "Country/region"
msgstr "Страна/регион"
msgid "Province/city"
msgstr "Регион/город"
msgid "Network organization"
msgstr "Сетевая организация"
msgid "Not enough free space for this database."
msgstr "Недостаточно места для этой базы."
msgid "Required space"
msgstr "Требуемое место"
msgid "Database ready"
msgstr "База готова"
msgid "Listen Address"
msgstr "Адрес прослушивания"
msgid "IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces."
msgstr "IP-адрес прослушивания Bandix. Используйте 127.0.0.1 для локального доступа или 0.0.0.0 / :: для всех интерфейсов."
+190 -31
View File
@@ -221,12 +221,6 @@ msgstr "WAN 已上传"
msgid "WAN Downloaded"
msgstr "WAN 已下载"
msgid "Total Upload"
msgstr "总上传速率"
msgid "Total Download"
msgstr "总下载速率"
msgid "LAN Upload"
msgstr "LAN 上传速率"
@@ -419,18 +413,12 @@ msgstr "第"
msgid "of"
msgstr "页,共"
msgid "Total"
msgstr "全部"
msgid "records"
msgstr "条记录"
msgid "Per Page"
msgstr "每页显示"
msgid ""
msgstr "条"
msgid "Total Queries"
msgstr "总查询数"
@@ -852,7 +840,7 @@ msgid "Please select at least one day"
msgstr "请至少选择一天"
msgid "No scheduled rules yet, click \"Add Rule\" to start setting"
msgstr "还没有定时限速规则,点击"添加规则"开始设置"
msgstr "还没有定时限速规则,点击\"添加规则\"开始设置"
msgid "Loading..."
msgstr "加载中..."
@@ -935,18 +923,6 @@ msgstr "最大值"
msgid "Minimum"
msgstr "最小值"
msgid "WAN Upload"
msgstr "WAN 上传"
msgid "WAN Download"
msgstr "WAN 下载"
msgid "WAN Uploaded"
msgstr "WAN 上传量"
msgid "WAN Downloaded"
msgstr "WAN 下载量"
msgid "Clear Traffic Data"
msgstr "删除流量数据"
@@ -1079,9 +1055,6 @@ msgstr "下载并安装"
msgid "Manual Download"
msgstr "手动下载"
msgid "Close"
msgstr "关闭"
msgid "Starting installation... The page will refresh automatically in 30 seconds."
msgstr "开始安装... 页面将在30秒后自动刷新。"
@@ -1097,9 +1070,6 @@ msgstr "有更新,点击前往设置"
msgid "Traffic Statistics"
msgstr "流量统计"
msgid "Traffic Statistics"
msgstr "流量统计"
msgid "Device Usage Ranking"
msgstr "设备用量排行"
@@ -1378,3 +1348,192 @@ msgstr "每分钟"
msgid "Show reply direction"
msgstr "显示回复方向"
msgid "Available space"
msgstr "可用空间"
msgid "Cannot prepare storage. Check free space and directory permissions."
msgstr "无法准备存储,请检查剩余空间和目录权限。"
msgid "Checking database version…"
msgstr "正在检查数据库版本…"
msgid "Checking storage…"
msgstr "正在检查存储空间…"
msgid "Choose an uncompressed .mmdb file within the upload size limit."
msgstr "请选择未压缩且未超过上传大小限制的 .mmdb 文件。"
msgid "Country/region + network organization — approximately 12 MiB"
msgstr "国家/地区 + 网络组织 · 约 12 MiB"
msgid "Country/region — approximately 3.3 MiB"
msgstr "国家/地区 · 约 3.3 MiB"
msgid "Data source"
msgstr "数据来源"
msgid "Data terms"
msgstr "数据使用条款"
msgid "Database contents"
msgstr "数据库内容"
msgid "Database directory"
msgstr "数据库目录"
msgid "Database enabled"
msgstr "数据库已启用"
msgid "Database is up to date"
msgstr "数据库已是最新版本"
msgid "Database operation failed"
msgstr "数据库操作失败"
msgid "Database operation failed. Retry or upload a local database."
msgstr "数据库操作失败,请重试或上传本地数据库。"
msgid "Database upload failed"
msgstr "数据库上传失败"
msgid "Database validation failed. The previous database is unchanged."
msgstr "数据库校验失败,原数据库未更改。"
msgid "Delete"
msgstr "删除"
msgid "Delete GeoIP databases"
msgstr "删除 IP 归属地数据库"
msgid "Disabled"
msgstr "已停用"
msgid "Documentation address"
msgstr "文档示例地址"
msgid "Download and enable"
msgstr "下载并启用"
msgid "Download cancelled"
msgstr "下载已取消"
msgid "Downloading database…"
msgstr "正在下载数据库…"
msgid "Enable IP location lookup"
msgstr "启用 IP 归属地查询"
msgid "Enabled"
msgstr "已启用"
msgid "GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix."
msgstr "IP 归属地服务不可用,请启用连接监控并应用设置,或更新 Bandix。"
msgid "IP location database"
msgstr "IP 归属地数据库"
msgid "Importing database…"
msgstr "正在导入数据库…"
msgid "Link-local address"
msgstr "链路本地地址"
msgid "Loading database…"
msgstr "正在加载数据库…"
msgid "Local network"
msgstr "局域网"
msgid "Loopback"
msgstr "回环地址"
msgid "Maximum upload size"
msgstr "上传大小上限"
msgid "Multicast"
msgstr "组播地址"
msgid "Not installed"
msgstr "未安装"
msgid "Private address"
msgstr "私有地址"
msgid "Province/city (uploaded database)"
msgstr "省市(已上传的数据库)"
msgid "Province/city + network organization — approximately 57 MiB"
msgstr "省市 + 网络组织 · 约 57 MiB"
msgid "Remove installed databases and disable IP location lookup?"
msgstr "删除已安装的数据库并停用 IP 归属地查询?"
msgid "Reserved address"
msgstr "保留地址"
msgid "Shared address (CGNAT)"
msgstr "共享地址(CGNAT)"
msgid "Storage used"
msgstr "存储占用"
msgid "The installed database could not be loaded. Download or upload it again."
msgstr "无法加载已安装的数据库,请重新下载或上传。"
msgid "Unknown"
msgstr "未知"
msgid "Unknown location"
msgstr "归属地未知"
msgid "Unspecified address"
msgstr "未指定地址"
msgid "Update database"
msgstr "更新数据库"
msgid "Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first."
msgstr "可上传未压缩的 Country、City 或 ASN .mmdb 文件。添加 ASN 前,请先安装 Country 或 City 数据库。"
msgid "Upload and enable"
msgstr "上传并启用"
msgid "Upload database"
msgstr "上传数据库"
msgid "Uploading database…"
msgstr "正在上传数据库…"
msgid "Use persistent storage or an external drive. Save and apply directory changes before downloading."
msgstr "请使用持久存储或外接磁盘。更改目录后,请先保存并应用,再下载数据库。"
msgid "Verifying database…"
msgstr "正在校验数据库…"
msgid "Version"
msgstr "版本"
msgid "Country/region"
msgstr "国家/地区"
msgid "Province/city"
msgstr "省市"
msgid "Network organization"
msgstr "网络组织"
msgid "Not enough free space for this database."
msgstr "没有足够空间安装此数据库。"
msgid "Required space"
msgstr "所需空间"
msgid "Database ready"
msgstr "数据库已就绪"
msgid "Listen Address"
msgstr "监听地址"
msgid "IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces."
msgstr "Bandix 监听的 IP 地址。127.0.0.1 仅供本机访问,0.0.0.0 / :: 监听所有接口。"
+190 -31
View File
@@ -221,12 +221,6 @@ msgstr "WAN 已上傳"
msgid "WAN Downloaded"
msgstr "WAN 已下載"
msgid "Total Upload"
msgstr "總上傳速率"
msgid "Total Download"
msgstr "總下載速率"
msgid "LAN Upload"
msgstr "LAN 上傳速率"
@@ -422,18 +416,12 @@ msgstr "第"
msgid "of"
msgstr "頁,共"
msgid "Total"
msgstr "全部"
msgid "records"
msgstr "筆記錄"
msgid "Per Page"
msgstr "每頁顯示"
msgid ""
msgstr "筆"
msgid "Total Queries"
msgstr "總查詢數"
@@ -855,7 +843,7 @@ msgid "Please select at least one day"
msgstr "請至少選擇一天"
msgid "No scheduled rules yet, click \"Add Rule\" to start setting"
msgstr "還沒有定時限速規則,點擊"新增規則"開始設定"
msgstr "還沒有定時限速規則,點擊\"新增規則\"開始設定"
msgid "Loading..."
msgstr "載入中..."
@@ -938,18 +926,6 @@ msgstr "最大值"
msgid "Minimum"
msgstr "最小值"
msgid "WAN Upload"
msgstr "WAN 上傳"
msgid "WAN Download"
msgstr "WAN 下載"
msgid "WAN Uploaded"
msgstr "WAN 上傳量"
msgid "WAN Downloaded"
msgstr "WAN 下載量"
msgid "Clear Traffic Data"
msgstr "刪除流量數據"
@@ -1082,9 +1058,6 @@ msgstr "下載並安裝"
msgid "Manual Download"
msgstr "手動下載"
msgid "Close"
msgstr "關閉"
msgid "Starting installation... The page will refresh automatically in 30 seconds."
msgstr "開始安裝... 頁面將在30秒後自動重新整理。"
@@ -1094,9 +1067,6 @@ msgstr "更新後請手動清空瀏覽器快取。"
msgid "Traffic Statistics"
msgstr "流量統計"
msgid "Traffic Statistics"
msgstr "流量統計"
msgid "Device Usage Ranking"
msgstr "設備用量排行"
@@ -1351,3 +1321,192 @@ msgstr "無法使用"
msgid "Show reply direction"
msgstr "顯示回覆方向"
msgid "Available space"
msgstr "可用空間"
msgid "Cannot prepare storage. Check free space and directory permissions."
msgstr "無法準備儲存空間,請檢查剩餘空間和目錄權限。"
msgid "Checking database version…"
msgstr "正在檢查資料庫版本…"
msgid "Checking storage…"
msgstr "正在檢查儲存空間…"
msgid "Choose an uncompressed .mmdb file within the upload size limit."
msgstr "請選擇未壓縮且未超過上傳大小限制的 .mmdb 檔案。"
msgid "Country/region + network organization — approximately 12 MiB"
msgstr "國家/地區 + 網路組織 · 約 12 MiB"
msgid "Country/region — approximately 3.3 MiB"
msgstr "國家/地區 · 約 3.3 MiB"
msgid "Data source"
msgstr "資料來源"
msgid "Data terms"
msgstr "資料使用條款"
msgid "Database contents"
msgstr "資料庫內容"
msgid "Database directory"
msgstr "資料庫目錄"
msgid "Database enabled"
msgstr "資料庫已啟用"
msgid "Database is up to date"
msgstr "資料庫已是最新版本"
msgid "Database operation failed"
msgstr "資料庫操作失敗"
msgid "Database operation failed. Retry or upload a local database."
msgstr "資料庫操作失敗,請重試或上傳本機資料庫。"
msgid "Database upload failed"
msgstr "資料庫上傳失敗"
msgid "Database validation failed. The previous database is unchanged."
msgstr "資料庫驗證失敗,原資料庫未變更。"
msgid "Delete"
msgstr "刪除"
msgid "Delete GeoIP databases"
msgstr "刪除 IP 歸屬地資料庫"
msgid "Disabled"
msgstr "已停用"
msgid "Documentation address"
msgstr "文件範例位址"
msgid "Download and enable"
msgstr "下載並啟用"
msgid "Download cancelled"
msgstr "下載已取消"
msgid "Downloading database…"
msgstr "正在下載資料庫…"
msgid "Enable IP location lookup"
msgstr "啟用 IP 歸屬地查詢"
msgid "Enabled"
msgstr "已啟用"
msgid "GeoIP service is unavailable. Enable connection monitoring and apply settings, or update Bandix."
msgstr "IP 歸屬地服務無法使用,請啟用連線監控並套用設定,或更新 Bandix。"
msgid "IP location database"
msgstr "IP 歸屬地資料庫"
msgid "Importing database…"
msgstr "正在匯入資料庫…"
msgid "Link-local address"
msgstr "鏈路本機位址"
msgid "Loading database…"
msgstr "正在載入資料庫…"
msgid "Local network"
msgstr "區域網路"
msgid "Loopback"
msgstr "回送位址"
msgid "Maximum upload size"
msgstr "上傳大小上限"
msgid "Multicast"
msgstr "多點傳送位址"
msgid "Not installed"
msgstr "未安裝"
msgid "Private address"
msgstr "私有位址"
msgid "Province/city (uploaded database)"
msgstr "省市(已上傳的資料庫)"
msgid "Province/city + network organization — approximately 57 MiB"
msgstr "省市 + 網路組織 · 約 57 MiB"
msgid "Remove installed databases and disable IP location lookup?"
msgstr "刪除已安裝的資料庫並停用 IP 歸屬地查詢?"
msgid "Reserved address"
msgstr "保留位址"
msgid "Shared address (CGNAT)"
msgstr "共用位址(CGNAT)"
msgid "Storage used"
msgstr "儲存用量"
msgid "The installed database could not be loaded. Download or upload it again."
msgstr "無法載入已安裝的資料庫,請重新下載或上傳。"
msgid "Unknown"
msgstr "未知"
msgid "Unknown location"
msgstr "歸屬地未知"
msgid "Unspecified address"
msgstr "未指定位址"
msgid "Update database"
msgstr "更新資料庫"
msgid "Upload an uncompressed Country, City or ASN .mmdb file. To add ASN, install a Country or City database first."
msgstr "可上傳未壓縮的 Country、City 或 ASN .mmdb 檔案。新增 ASN 前,請先安裝 Country 或 City 資料庫。"
msgid "Upload and enable"
msgstr "上傳並啟用"
msgid "Upload database"
msgstr "上傳資料庫"
msgid "Uploading database…"
msgstr "正在上傳資料庫…"
msgid "Use persistent storage or an external drive. Save and apply directory changes before downloading."
msgstr "請使用持續性儲存或外接磁碟。變更目錄後,請先儲存並套用,再下載資料庫。"
msgid "Verifying database…"
msgstr "正在驗證資料庫…"
msgid "Version"
msgstr "版本"
msgid "Country/region"
msgstr "國家/地區"
msgid "Province/city"
msgstr "省市"
msgid "Network organization"
msgstr "網路組織"
msgid "Not enough free space for this database."
msgstr "沒有足夠空間安裝此資料庫。"
msgid "Required space"
msgstr "所需空間"
msgid "Database ready"
msgstr "資料庫已就緒"
msgid "Listen Address"
msgstr "監聽位址"
msgid "IP address for Bandix to listen on. Use 127.0.0.1 for local access or 0.0.0.0 / :: for all interfaces."
msgstr "Bandix 監聽的 IP 位址。127.0.0.1 僅供本機存取,0.0.0.0 / :: 監聽所有介面。"
@@ -3,9 +3,16 @@
. /usr/share/libubox/jshn.sh
# 从UCI配置读取端口号,如果读取失败则使用默认端口8686
BANDIX_PORT=$(uci get bandix.general.port 2>/dev/null || echo "8686")
readonly BANDIX_API_BASE="http://127.0.0.1:$BANDIX_PORT"
# Wildcard listening addresses must be reached through loopback on the router.
BANDIX_HOST=$(uci -q get bandix.general.host)
BANDIX_PORT=$(uci -q get bandix.general.port)
BANDIX_PORT=${BANDIX_PORT:-8686}
case "$BANDIX_HOST" in
''|0.0.0.0) BANDIX_HOST='127.0.0.1' ;;
::) BANDIX_HOST='[::1]' ;;
*:*) BANDIX_HOST="[$BANDIX_HOST]" ;;
esac
readonly BANDIX_API_BASE="http://$BANDIX_HOST:$BANDIX_PORT"
readonly BANDIX_DEVICES_API="$BANDIX_API_BASE/api/traffic/devices"
readonly BANDIX_LIMITS_API="$BANDIX_API_BASE/api/traffic/limits"
readonly BANDIX_METRICS_API="$BANDIX_API_BASE/api/traffic/metrics"
@@ -421,12 +428,13 @@ get_connection_flows() {
[ -n "$state" ] && query_params="${query_params}state=$(printf '%s' "$state" | sed 's/ /%20/g')&"
[ -n "$page" ] && query_params="${query_params}page=$page&"
[ -n "$page_size" ] && query_params="${query_params}page_size=$page_size&"
if [ -n "$page" ] || [ -n "$page_size" ]; then query_params="${query_params}geoip=1&"; fi
query_params=$(echo "$query_params" | sed 's/&$//')
local url="$BANDIX_CONNECTION_FLOWS_API"
[ -n "$query_params" ] && url="${url}?${query_params}"
local response=$(curl -s --connect-timeout 2 --max-time 5 -X GET "$url" 2>/dev/null)
local response=$(curl -s --connect-timeout 2 --max-time 15 -X GET "$url" 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$response" ]; then
make_error "Failed to connect to Bandix service"
return
@@ -434,6 +442,44 @@ get_connection_flows() {
echo "$response"
}
# GeoIP management is proxied to the router itself; writes require the LuCI
# write ACL. Accept only action/profile identifiers, never arbitrary URLs/paths.
get_geoip_status() {
local response
response=$(curl -s --connect-timeout 2 --max-time 8 "$BANDIX_API_BASE/api/geoip/status" 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$response" ]; then
make_error "GeoIP service is unavailable"
return
fi
printf '%s\n' "$response"
}
manage_geoip() {
local action="$1" profile="$2" enabled="$3" payload response
json_init
case "$action" in
download)
case "$profile" in country|country_asn|city|city_asn) ;; *) make_error "Invalid database profile"; return ;; esac
json_add_string "action" "download"
json_add_string "profile" "$profile"
;;
enable)
json_add_string "action" "enable"
case "$enabled" in 1|true) json_add_boolean "enabled" 1 ;; 0|false) json_add_boolean "enabled" 0 ;; *) make_error "Invalid enabled value"; return ;; esac
;;
cancel|delete|import) json_add_string "action" "$action" ;;
*) make_error "Invalid GeoIP action"; return ;;
esac
payload=$(json_dump)
json_cleanup
response=$(curl -s --connect-timeout 2 --max-time 8 -X POST -H 'Content-Type: application/json' --data-binary "$payload" "$BANDIX_API_BASE/api/geoip/manage" 2>/dev/null)
if [ $? -ne 0 ] || [ -z "$response" ]; then
make_error "GeoIP service is unavailable"
return
fi
printf '%s\n' "$response"
}
# 获取 DNS 查询记录
get_dns_queries() {
# 检查 DNS 监控是否启用
@@ -1311,6 +1357,14 @@ case "$1" in
json_add_string "mac"
json_close_object
json_add_object "getGeoipStatus"
json_close_object
json_add_object "manageGeoip"
json_add_string "action"
json_add_string "profile"
json_add_string "enabled"
json_close_object
json_add_object "getConnection"
json_close_object
@@ -1525,6 +1579,20 @@ case "$1" in
fi
delete_device "$mac"
;;
getGeoipStatus)
get_geoip_status
;;
manageGeoip)
input=""
read -r input
action="$(printf '%s' "$input" | jsonfilter -e '$.action' 2>/dev/null)"
[ -z "$action" ] && action="$(printf '%s' "$input" | jsonfilter -e '$[0]' 2>/dev/null)"
profile="$(printf '%s' "$input" | jsonfilter -e '$.profile' 2>/dev/null)"
[ -z "$profile" ] && profile="$(printf '%s' "$input" | jsonfilter -e '$[1]' 2>/dev/null)"
enabled="$(printf '%s' "$input" | jsonfilter -e '$.enabled' 2>/dev/null)"
[ -z "$enabled" ] && enabled="$(printf '%s' "$input" | jsonfilter -e '$[2]' 2>/dev/null)"
manage_geoip "$action" "$profile" "$enabled"
;;
getConnection)
# logger "luci.bandix: getConnection called"
get_connection_devices
@@ -27,7 +27,8 @@
"getTrafficUsageRanking",
"getTrafficUsageIncrements",
"getRateLimitWhitelist",
"getTrafficQuotas"
"getTrafficQuotas",
"getGeoipStatus"
]
},
"uci": [
@@ -68,12 +69,19 @@
"updateScheduleLimit",
"getTrafficQuotas",
"setTrafficQuota",
"deleteTrafficQuota"
"deleteTrafficQuota",
"getGeoipStatus",
"manageGeoip"
]
},
"uci": [
"bandix"
]
],
"file": {
"/tmp/bandix-geoip-upload.mmdb": [
"write"
]
}
}
}
}
+2 -2
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-clashoo
PKG_VERSION:=1.31.0
PKG_RELEASE:=6
PKG_RELEASE:=7
PKG_MAINTAINER:=kenzok8
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
@@ -91,7 +91,7 @@ define Package/luci-i18n-clashoo-zh-cn/postinst
if [ -z "$${IPKG_INSTROOT}" ]; then
# just clear the LuCI cache so the new translations load on next request;
# no service restart needed (and none that would drop the login session).
rm -rf /tmp/luci*
rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
fi
exit 0
endef
@@ -15,7 +15,9 @@ function mkdtemp(tpl) {
}
const BINARY_PATHS = [
'/usr/bin/mihomo-stable',
'/usr/share/clashoo/bin/mihomo-stable',
'/usr/libexec/clashoo/mihomo-stable',
'/usr/share/clashoo/bin/mihomo-alpha',
'/usr/bin/mihomo',
'/usr/bin/clash-meta',
'/usr/bin/clash',
@@ -283,8 +285,8 @@ if (family === 'mihomo') {
}
}
let channel = get_core_channel('mihomo');
if (channel == 'stable' && access('/usr/bin/mihomo-stable', 'x')) return '/usr/bin/mihomo-stable';
if (channel == 'alpha' && access('/usr/bin/mihomo', 'x')) return '/usr/bin/mihomo';
if (channel == 'stable') return selected_mihomo_stable();
if (channel == 'alpha') return access('/usr/share/clashoo/bin/mihomo-alpha', 'x') ? '/usr/share/clashoo/bin/mihomo-alpha' : '';
if (channel == 'smart') {
for (let path in SMART_BINARY_PATHS)
if (access(path, 'x')) return path;
@@ -371,7 +373,7 @@ c.set('clashoo', 'config', 'core', legacy);
}
function has_mihomo_stable() {
if (access('/usr/bin/mihomo-stable', 'x')) return true;
if (selected_mihomo_stable()) return true;
if (system("[ -x /usr/bin/clash-meta ] && [ ! -L /usr/bin/clash-meta ]") != 0) return false;
let version = get_core_version('/usr/bin/clash-meta');
return !!version && !match(version, /(alpha|beta|rc|pre|smart)/i);
@@ -387,7 +389,7 @@ if (core == 'mihomo' && dcore == '2') {
return { error: 'mihomo_stable_missing', message: '未检测到 mihomo 稳定版,请先在“组件更新”中更新稳定版' };
}
if (core == 'mihomo' && dcore == '3') {
if (access('/usr/bin/mihomo', 'x')) return null;
if (access('/usr/share/clashoo/bin/mihomo-alpha', 'x')) return null;
return { error: 'mihomo_alpha_missing', message: '未检测到 mihomo Alpha,请先在“组件更新”中更新 Alpha' };
}
if (core == 'singbox' && dcore == '4') {
@@ -887,6 +889,23 @@ if (m) return m[1];
return full;
}
function selected_mihomo_stable() {
let bundled = '/usr/libexec/clashoo/mihomo-stable';
let manual = '/usr/share/clashoo/bin/mihomo-stable';
if (access(manual, 'x') && read_first_line('/usr/share/clashoo/clash_meta_version') == 'custom-url') return manual;
if (!access(bundled, 'x')) return access(manual, 'x') ? manual : '';
if (!access(manual, 'x')) return bundled;
let bv = match(core_short_version(bundled), /^v?([0-9]+)\.([0-9]+)\.([0-9]+)$/);
let mv = match(core_short_version(manual), /^v?([0-9]+)\.([0-9]+)\.([0-9]+)$/);
if (!bv) return mv ? manual : bundled;
if (!mv) return bundled;
for (let i = 1; i <= 3; i++) {
if (int(mv[i]) > int(bv[i])) return manual;
if (int(mv[i]) < int(bv[i])) return bundled;
}
return manual;
}
function component_installed_label(id) {
if (id == 'clashoo') return pkg_version('clashoo') || '未安装';
if (id == 'luci') return pkg_version('luci-app-clashoo') || '未安装';
@@ -923,12 +942,11 @@ return !!match(ver || '', /(alpha|beta|rc|pre|smart)/i);
function component_installed_versions(id) {
let out = {};
if (id == 'mihomo') {
let stable = access('/usr/bin/mihomo-stable', 'x') ? read_first_line('/usr/share/clashoo/clash_meta_version') : '';
if (!stable && access('/usr/bin/mihomo-stable', 'x')) stable = core_short_version('/usr/bin/mihomo-stable');
let stable_bin = selected_mihomo_stable();
let stable = stable_bin ? core_short_version(stable_bin) : '';
if (is_prerelease_label(stable)) stable = '';
let alpha = read_first_line('/usr/share/clashoo/mihomo_version');
let alpha = access('/usr/share/clashoo/bin/mihomo-alpha', 'x') ? core_short_version('/usr/share/clashoo/bin/mihomo-alpha') : '';
if (match(alpha, /^smart-/)) alpha = '';
if (!alpha && access('/usr/bin/mihomo', 'x')) alpha = core_short_version('/usr/bin/mihomo');
out.stable = stable || '';
out.alpha = mihomo_alpha_label(alpha);
return out;
@@ -2815,7 +2833,7 @@ let api = get_clash_api_auth();
health_status, health_detail, has_tun_device,
core_type: configured_core, dcore, local_ip,
has_mihomo_stable: has_mihomo_stable(),
has_mihomo_alpha: !!access('/usr/bin/mihomo', 'x'),
has_mihomo_alpha: !!access('/usr/share/clashoo/bin/mihomo-alpha', 'x'),
has_singbox_stable: !!access(SINGBOX_BINARY_PATHS[0], 'x'),
has_singbox_alpha: !!access(SINGBOX_BINARY_PATHS[1], 'x'),
has_smart: !!find_smart_binary() };
-28
View File
@@ -1,28 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=kai
PKG_VERSION:=1.0.2-r5
PKG_RELEASE:=
LUCI_DEPENDS:=+kai +luci-compat +luci-lib-linkeaseauth +linkease-app-entry
LUCI_MINIFY_CSS:=0
LUCI_MINIFY_JS:=0
define Package/luci-app-kai/conffiles
/etc/config/kai
endef
define Package/luci-app-kai/postrm
#!/bin/sh
rm -f /tmp/luci-indexcache
exit 0
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
-29
View File
@@ -1,29 +0,0 @@
local http = require "luci.http"
module("luci.controller.kai", package.seeall)
function index()
if not nixio.fs.access("/etc/config/kai") then
return
end
local page
page = entry({"admin", "services","kai"}, cbi("kai"), _("KAI"), 100)
page.dependent = true
entry({"admin", "services", "kai_status"}, call("kai_status"))
end
function kai_status()
local sys = require "luci.sys"
local uci = require "luci.model.uci".cursor()
local port = tonumber(uci:get_first("kai", "kai", "port")) or 8197
if port < 1 or port > 65535 or port % 1 ~= 0 then
port = 8197
end
local status = {
running = (sys.call("pidof kai_bin >/dev/null") == 0),
port = port
}
http.prepare_content("application/json")
http.write_json(status)
end
-32
View File
@@ -1,32 +0,0 @@
local m, s
m = Map("kai", translate("KAI"), translate("KAI is an efficient AI tool."))
m:section(SimpleSection).template = "kai/kai_status"
s=m:section(TypedSection, "kai", translate("Global settings"))
s.addremove=false
s.anonymous=true
s:option(Flag, "enabled", translate("Enable")).rmempty=false
local kai_model = require "luci.model.kai"
local blocks = kai_model.blocks()
local home = kai_model.home()
local data_dir = s:option(Value, "data_dir", translate("Data directory"))
data_dir.rmempty = false
data_dir.description = translate("Required. KAI session will store cwd/cache/data/config/state under this directory (subfolders: cwd, cache, data, config, state).")
local paths, default_path = kai_model.find_paths(blocks, home, "Configs")
for _, val in pairs(paths) do
data_dir:value(val, val)
end
data_dir.default = default_path
local port = s:option(Value, "port", translate("API port"))
port.default = "8197"
port.rmempty = false
port.datatype = "port"
port.description = translate("Port for KAI HTTP server (kai_bin). kai_session will read OPENCODE_CONFIG via 127.0.0.1:<port>.")
return m
-54
View File
@@ -1,54 +0,0 @@
local jsonc = require "luci.jsonc"
local kai = {}
kai.blocks = function()
local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
local vals = {}
if f then
local ret = f:read("*all")
f:close()
local obj = jsonc.parse(ret)
for _, val in pairs(obj and obj["blockdevices"] or {}) do
local fsize = val["fssize"]
if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
vals[#vals + 1] = val["mountpoint"]
end
end
end
return vals
end
kai.home = function()
local uci = require "luci.model.uci".cursor()
local home_dirs = {}
home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root")
home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"] .. "/Configs")
home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"] .. "/Public")
home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"] .. "/Downloads")
home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"] .. "/Caches")
return home_dirs
end
kai.find_paths = function(blocks, home_dirs, path_name)
local default_path = ""
local paths = {}
default_path = home_dirs[path_name] .. "/KAI"
if #blocks == 0 then
table.insert(paths, default_path)
else
for _, val in pairs(blocks) do
table.insert(paths, val .. "/" .. path_name .. "/KAI")
end
local without_conf_dir = "/root/" .. path_name .. "/KAI"
if default_path == without_conf_dir then
default_path = paths[1]
end
end
return paths, default_path
end
return kai
@@ -1,23 +0,0 @@
<script type="text/javascript">//<![CDATA[
var kaiOpenUrl = '<%=url("admin/services/linkease_apps/open")%>?id=kai';
XHR.poll(5, '<%=url("admin/services/kai_status")%>', null,function(x, st){
var el = document.getElementById('kai_status');
if (st && el){
if(!st.running){
el.innerHTML = '<br/><em style=\"color:red\"><%:The KAI service is not running.%></em>';
}
if (st.running){
el.innerHTML = '<br/><em style=\"color:green\"><%:The KAI service is running.%></em>'
+ "<br/><br/><input class=\"btn cbi-button cbi-button-apply\" type=\"button\" value=\" <%:Click to open KAI%> \" onclick=\"window.open(kaiOpenUrl, '_blank', 'noopener')\"/>";
}
}
});
//]]></script>
<fieldset class="cbi-section">
<legend><%:Status%></legend>
<p id="kai_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>