mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-29 03:45:13 +08:00
update 2026-07-05 01:02:55
This commit is contained in:
1 parent
37125b3bbc
commit
76aa39b679
46 files changed
+667
-2545
No files matched your search
+31
-17
@@ -1,22 +1,24 @@
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=adguardhome
|
||||
PKG_VERSION:=0.107.51
|
||||
PKG_VERSION:=0.107.77
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/AdGuardHome/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=dea9685282e55940925ff7211f7d72072de5b98134c8f01d5569c04284681650
|
||||
PKG_HASH:=1db8e53238c3ba8aecfbe0b68ba6197435dae19fd3512c70c68d90b7239b7464
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION)
|
||||
|
||||
FRONTEND_DEST:=$(PKG_NAME)-frontend-$(PKG_VERSION).tar.gz
|
||||
FRONTEND_URL:=https://github.com/AdguardTeam/AdGuardHome/releases/download/v$(PKG_VERSION)/
|
||||
FRONTEND_HASH:=3c455340365e4dc3babedfc65e52ab93334a40568e8a7b84eb4aa1cd1a6b3a71
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-only
|
||||
PKG_LICENSE_FILES:=LICENSE.txt
|
||||
PKG_MAINTAINER:=Dobroslaw Kijowski <dobo90@gmail.com>
|
||||
PKG_CPE_ID:=cpe:/a:adguard:adguardhome
|
||||
PKG_MAINTAINER:=Dobroslaw Kijowski <dobo90@gmail.com>, George Sapkin <george@sapk.in>
|
||||
|
||||
PKG_BUILD_DEPENDS:=golang/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
@@ -25,16 +27,15 @@ PKG_BUILD_FLAGS:=no-mips16
|
||||
GO_PKG:=github.com/AdguardTeam/AdGuardHome
|
||||
GO_PKG_BUILD_PKG:=$(GO_PKG)
|
||||
|
||||
AGH_BUILD_TIME:=$(shell date -d @$(SOURCE_DATE_EPOCH) +%FT%TZ%z)
|
||||
GO_PKG_LDFLAGS_X:= \
|
||||
$(GO_PKG)/internal/version.channel=release \
|
||||
$(GO_PKG)/internal/version.version=v$(PKG_VERSION) \
|
||||
$(GO_PKG)/internal/version.buildtime=$(AGH_BUILD_TIME) \
|
||||
$(GO_PKG)/internal/version.committime=$(SOURCE_DATE_EPOCH) \
|
||||
$(GO_PKG)/internal/version.goarm=$(GO_ARM) \
|
||||
$(GO_PKG)/internal/version.gomips=$(GO_MIPS)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include ../../lang/golang/golang-package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||
|
||||
define Package/adguardhome
|
||||
SECTION:=net
|
||||
@@ -42,10 +43,11 @@ define Package/adguardhome
|
||||
TITLE:=Network-wide ads and trackers blocking DNS server
|
||||
URL:=https://github.com/AdguardTeam/AdGuardHome
|
||||
DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle
|
||||
USERID:=adguardhome=853:adguardhome=853
|
||||
endef
|
||||
|
||||
define Package/adguardhome/conffiles
|
||||
/etc/adguardhome.yaml
|
||||
/etc/adguardhome/adguardhome.yaml
|
||||
/etc/config/adguardhome
|
||||
endef
|
||||
|
||||
@@ -53,25 +55,37 @@ define Package/adguardhome/description
|
||||
Free and open source, powerful network-wide ads and trackers blocking DNS server.
|
||||
endef
|
||||
|
||||
FRONTEND_FILE:=$(PKG_NAME)-frontend-$(PKG_VERSION).tar.gz
|
||||
define Download/adguardhome-frontend
|
||||
URL:=https://github.com/AdguardTeam/AdGuardHome/releases/download/v$(PKG_VERSION)/
|
||||
URL:=$(FRONTEND_URL)
|
||||
URL_FILE:=AdGuardHome_frontend.tar.gz
|
||||
FILE:=$(FRONTEND_FILE)
|
||||
HASH:=253d05185865840e14e841e4245c3fdb0fdcca28649902303d3869e0bd07cfd7
|
||||
FILE:=$(FRONTEND_DEST)
|
||||
HASH:=$(FRONTEND_HASH)
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
|
||||
gzip -dc $(DL_DIR)/$(FRONTEND_FILE) | $(HOST_TAR) -C $(PKG_BUILD_DIR)/ $(TAR_OPTIONS)
|
||||
gzip -dc $(DL_DIR)/$(FRONTEND_DEST) | $(HOST_TAR) -C $(PKG_BUILD_DIR)/ $(TAR_OPTIONS)
|
||||
endef
|
||||
|
||||
define Package/adguardhome/install
|
||||
$(call GoPackage/Package/Install/Bin,$(1))
|
||||
$(INSTALL_DIR) $(1)/etc/capabilities
|
||||
$(INSTALL_CONF) ./files/adguardhome.json $(1)/etc/capabilities/adguardhome.json
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./files/adguardhome.conf $(1)/etc/config/adguardhome
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/adguardhome.init $(1)/etc/init.d/adguardhome
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/sysctl.d
|
||||
$(INSTALL_CONF) ./files/adguardhome.sysctl $(1)/etc/sysctl.d/50-adguardhome.conf
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/adguardhome.defaults $(1)/etc/uci-defaults/adguardhome
|
||||
endef
|
||||
|
||||
$(eval $(call Download,adguardhome-frontend))
|
||||
$(eval $(call GoBinPackage,adguardhome))
|
||||
$(eval $(call BuildPackage,adguardhome))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
config adguardhome 'config'
|
||||
option enabled '0'
|
||||
# All paths must be readable by the configured user
|
||||
option config_file '/etc/adguardhome/adguardhome.yaml'
|
||||
# Where to store persistent data by AdGuard Home
|
||||
option work_dir '/var/lib/adguardhome'
|
||||
option user 'adguardhome'
|
||||
option group 'adguardhome'
|
||||
option verbose '0'
|
||||
|
||||
# Files and directories that AdGuard Home has read-only access to
|
||||
# list jail_mount '/etc/ssl/adguardhome.crt'
|
||||
# list jail_mount '/etc/ssl/adguardhome.key'
|
||||
|
||||
# Files and directories that AdGuard Home has read-write access to
|
||||
# list jail_mount_rw '/path/to/dir'
|
||||
|
||||
# Advanced options. Modify at your own risk.
|
||||
|
||||
# More info: https://go.dev/doc/gc-guide#GOGC
|
||||
option gc '0'
|
||||
|
||||
# Max number of OS threads to use
|
||||
# 0 to match the number of CPUs (default)
|
||||
# >0 to explicitly specify concurrency
|
||||
option maxprocs '0'
|
||||
|
||||
# Soft memory limit in MB, 0 to disable
|
||||
option memlimit '0'
|
||||
@@ -0,0 +1,109 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# Migrate old config format only
|
||||
OLD_CONFIG_FILE=$(uci -q get adguardhome.config.config)
|
||||
OLD_CONFIG_FILE=${OLD_CONFIG_FILE:-/etc/adguardhome.yaml}
|
||||
OLD_CONFIG_NEW_OPT_FILE=$(uci -q get adguardhome.config.config_file)
|
||||
NEW_CONFIG_DIR=/etc/adguardhome
|
||||
NEW_CONFIG_FILE="$NEW_CONFIG_DIR/adguardhome.yaml"
|
||||
|
||||
start_service() {
|
||||
if ! /etc/init.d/adguardhome running; then
|
||||
/etc/init.d/adguardhome start
|
||||
fi
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
if /etc/init.d/adguardhome running; then
|
||||
/etc/init.d/adguardhome stop
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -f "$OLD_CONFIG_NEW_OPT_FILE" ] && [ "$OLD_CONFIG_NEW_OPT_FILE" != "$NEW_CONFIG_FILE" ]; then
|
||||
echo "Old AdGuard Home config found in '$OLD_CONFIG_NEW_OPT_FILE'"
|
||||
|
||||
USER=$(uci -q get adguardhome.config.user)
|
||||
USER=${USER:-adguardhome}
|
||||
|
||||
echo "AdGuard Home config is stored in a non-default path."
|
||||
echo "Ensure configured service user '$USER' can access it."
|
||||
|
||||
elif [ -f "$OLD_CONFIG_FILE" ] && [ "$OLD_CONFIG_FILE" != "$NEW_CONFIG_FILE" ]; then
|
||||
echo "Old AdGuard Home config found in '$OLD_CONFIG_FILE'"
|
||||
OLD_CONFIG_DIR=$(dirname "$OLD_CONFIG_FILE")
|
||||
|
||||
USER=$(uci -q get adguardhome.config.user)
|
||||
USER=${USER:-adguardhome}
|
||||
GROUP=$(uci -q get adguardhome.config.group)
|
||||
GROUP=${GROUP:-adguardhome}
|
||||
|
||||
CUR_CONFIG_FILE="$OLD_CONFIG_FILE"
|
||||
if [ "$OLD_CONFIG_DIR" = "/etc" ]; then
|
||||
echo "AdGuard Home config must be stored in its own directory. Migrating..."
|
||||
stop_service
|
||||
|
||||
echo "Using $USER:$GROUP for file ownership."
|
||||
|
||||
[ -d "$NEW_CONFIG_DIR" ] || mkdir -m 0700 -p "$NEW_CONFIG_DIR"
|
||||
mv "$OLD_CONFIG_FILE" "$NEW_CONFIG_FILE"
|
||||
chown -R "$USER":"$GROUP" "$NEW_CONFIG_DIR"
|
||||
CUR_CONFIG_FILE="$NEW_CONFIG_FILE"
|
||||
|
||||
echo "Config migrated to '$NEW_CONFIG_FILE'"
|
||||
|
||||
else
|
||||
echo "AdGuard Home config is stored in a non-default path."
|
||||
echo "Ensure configured service user '$USER' can access it."
|
||||
fi
|
||||
|
||||
uci set adguardhome.config.config_file="$CUR_CONFIG_FILE"
|
||||
uci -q delete adguardhome.config.config
|
||||
|
||||
# Use awk to split match on :, remove double quotes and trim leading and
|
||||
# trailing spaces
|
||||
cert_path=$(grep certificate_path: "$CUR_CONFIG_FILE" \
|
||||
| awk -F':' '{gsub(/"/, "", $2); gsub(/^ +| +$/, "", $2); print $2}')
|
||||
if [ -n "$cert_path" ]; then
|
||||
echo "Found custom 'certificate_path' pointing to '$cert_path'." \
|
||||
+ "Ensure configured service user '$USER' can access it."
|
||||
|
||||
stop_service
|
||||
|
||||
if ! uci -q show adguardhome.config.jail_mount | grep -q "$cert_path"; then
|
||||
uci add_list adguardhome.config.jail_mount="$cert_path"
|
||||
fi
|
||||
fi
|
||||
|
||||
private_key_path=$(grep private_key_path: "$CUR_CONFIG_FILE" \
|
||||
| awk -F':' '{gsub(/"/, "", $2); gsub(/^ +| +$/, "", $2); print $2}')
|
||||
if [ -n "$private_key_path" ]; then
|
||||
echo "Found custom 'private_key_path' pointing to '$private_key_path'." \
|
||||
+ "Ensure configured service user '$USER' can access it."
|
||||
|
||||
stop_service
|
||||
|
||||
if ! uci -q show adguardhome.config.jail_mount | grep -q "$private_key_path"; then
|
||||
uci add_list adguardhome.config.jail_mount="$private_key_path"
|
||||
fi
|
||||
fi
|
||||
|
||||
uci commit adguardhome
|
||||
start_service
|
||||
|
||||
elif [ -z "$OLD_CONFIG_NEW_OPT_FILE" ] && [ "$OLD_CONFIG_FILE" != "$NEW_CONFIG_FILE" ]; then
|
||||
echo "Old AdGuard Home config not found in '$OLD_CONFIG_FILE'"
|
||||
stop_service
|
||||
|
||||
# Service script will create the new config directory
|
||||
uci set adguardhome.config.config_file="$NEW_CONFIG_FILE"
|
||||
uci -q delete adguardhome.config.config
|
||||
echo "Config path changed to '$NEW_CONFIG_FILE'"
|
||||
|
||||
uci commit adguardhome
|
||||
start_service
|
||||
|
||||
else
|
||||
echo "AdGuard Home config is in its default path '$NEW_CONFIG_FILE'"
|
||||
fi
|
||||
@@ -0,0 +1,111 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# shellcheck disable=SC3043 # ash supports local
|
||||
|
||||
# matches dnsmasq
|
||||
START=19
|
||||
# stops before networking stops
|
||||
STOP=89
|
||||
|
||||
PROG=/usr/bin/AdGuardHome
|
||||
USE_PROCD=1
|
||||
|
||||
boot() {
|
||||
ADGUARDHOME_BOOT=1
|
||||
start "$@"
|
||||
}
|
||||
|
||||
start_service() {
|
||||
if [ -n "$ADGUARDHOME_BOOT" ]; then
|
||||
# Do not start yet, wait for triggers
|
||||
return 0
|
||||
fi
|
||||
|
||||
config_load 'adguardhome'
|
||||
|
||||
local config_name='config'
|
||||
local config_file config group user verbose work_dir workdir
|
||||
local enabled gc maxprocs memlimit
|
||||
|
||||
uci_validate_section 'adguardhome' 'adguardhome' "$config_name" \
|
||||
'enabled:bool:0' \
|
||||
'gc:uinteger:0' \
|
||||
'group:string:adguardhome' \
|
||||
'config:string' \
|
||||
'config_file:string:/etc/adguardhome/adguardhome.yaml' \
|
||||
'jail_mount:list(string)' \
|
||||
'jail_mount_rw:list(string)' \
|
||||
'maxprocs:uinteger:0' \
|
||||
'memlimit:uinteger:0' \
|
||||
'user:string:adguardhome' \
|
||||
'verbose:bool:0' \
|
||||
'workdir:string' \
|
||||
'work_dir:string:/var/lib/adguardhome'
|
||||
|
||||
[ "$enabled" -eq "1" ] || return 1
|
||||
|
||||
# Compatibility with older configs
|
||||
[ -n "$config" ] && config_file="$config"
|
||||
[ -n "$workdir" ] && work_dir="$workdir"
|
||||
|
||||
local config_dir
|
||||
config_dir=$(dirname "$config_file")
|
||||
if [ "$config_dir" = '/etc' ]; then
|
||||
echo 'AdGuard Home config must be stored in its own directory, and not in /etc' >&2
|
||||
return 1
|
||||
fi
|
||||
mkdir -m 0700 -p "$config_dir"
|
||||
chown -R "$user":"$group" "$config_dir"
|
||||
|
||||
mkdir -m 0700 -p "$work_dir"
|
||||
chown -R "$user":"$group" "$work_dir"
|
||||
|
||||
procd_open_instance adguardhome
|
||||
|
||||
procd_set_param command "$PROG"
|
||||
|
||||
[ "$gc" -le 0 ] || procd_append_param env GOGC="$gc"
|
||||
[ "$maxprocs" -le 0 ] || procd_append_param env GOMAXPROCS="$maxprocs"
|
||||
[ "$memlimit" -le 0 ] || procd_append_param env GOMEMLIMIT="$memlimit"
|
||||
|
||||
procd_append_param command --config "$config_file"
|
||||
procd_append_param command --logfile syslog
|
||||
procd_append_param command --no-check-update
|
||||
[ "$verbose" = 1 ] && procd_append_param command --verbose
|
||||
procd_append_param command --work-dir "$work_dir"
|
||||
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_set_param user "$user"
|
||||
procd_set_param group "$group"
|
||||
procd_set_param capabilities '/etc/capabilities/adguardhome.json'
|
||||
procd_set_param no_new_privs 1
|
||||
procd_set_param respawn
|
||||
|
||||
# log is needed for logging to syslog instead of stdout
|
||||
# procfs is needed to readlink /proc/self/exe
|
||||
procd_add_jail adguardhome log procfs
|
||||
|
||||
# config directory must be writable to write new config files
|
||||
procd_add_jail_mount_rw "$config_dir"
|
||||
procd_add_jail_mount_rw "$work_dir"
|
||||
|
||||
procd_add_jail_mount '/etc/hosts'
|
||||
procd_add_jail_mount '/etc/ssl/certs'
|
||||
config_list_foreach "$config_name" jail_mount procd_add_jail_mount
|
||||
config_list_foreach "$config_name" jail_mount_rw procd_add_jail_mount_rw
|
||||
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger adguardhome
|
||||
|
||||
if [ -n "$ADGUARDHOME_BOOT" ]; then
|
||||
# Wait for interfaces to be up before starting AdGuard Home for real.
|
||||
# Prevents issues like https://github.com/openwrt/packages/issues/21868.
|
||||
procd_add_raw_trigger 'interface.*.up' 5000 /etc/init.d/adguardhome restart
|
||||
fi
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"bounding": [
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
"CAP_NET_RAW"
|
||||
],
|
||||
"effective": [
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
"CAP_NET_RAW"
|
||||
],
|
||||
"ambient": [
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
"CAP_NET_RAW"
|
||||
],
|
||||
"permitted": [
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
"CAP_NET_RAW"
|
||||
],
|
||||
"inheritable": [
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
"CAP_NET_RAW"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# quic-go expects larger UDP send/receive buffers
|
||||
net.core.rmem_max = 7500000
|
||||
net.core.wmem_max = 7500000
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/client/src/__locales/zh-cn.json
|
||||
+++ b/client/src/__locales/zh-cn.json
|
||||
@@ -571,7 +571,7 @@
|
||||
"filters_interval": "过滤器更新间隔",
|
||||
"disabled": "已禁用",
|
||||
"username_label": "用户名",
|
||||
- "username_placeholder": "输入用户名",
|
||||
+ "username_placeholder": "默认用户名密码都是root",
|
||||
"password_label": "密码",
|
||||
"password_placeholder": "输入密码",
|
||||
"sign_in": "登入",
|
||||
@@ -1,9 +0,0 @@
|
||||
--- a/client/src/helpers/version.ts
|
||||
+++ b/client/src/helpers/version.ts
|
||||
@@ -13,5 +13,5 @@ export const areEqualVersions = (left: any, right: any) => {
|
||||
|
||||
const leftVersion = left.replace(/^v/, '');
|
||||
const rightVersion = right.replace(/^v/, '');
|
||||
- return leftVersion === rightVersion;
|
||||
+ return leftVersion >= rightVersion;
|
||||
};
|
||||
+19
-41
@@ -1,38 +1,36 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2017-2020 Yousong Zhou <yszhou4tech@gmail.com>
|
||||
# Copyright (C) 2021-2023 ImmortalWrt.org
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=aliyundrive-webdav
|
||||
PKG_VERSION:=2.3.3
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/messense/aliyundrive-webdav.git
|
||||
PKG_SOURCE_VERSION:=6e8eba62b4e50acf89681e3a67a3a693186dcd05
|
||||
PKG_MIRROR_HASH:=b6b1099c90818c5eb322bdae105d3df8d7a954d6e9ee7798c3c2412eed528640
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_MAINTAINER:=messense <messense@icloud.com>
|
||||
|
||||
PKG_LIBC:=musl
|
||||
ifeq ($(ARCH),arm)
|
||||
PKG_LIBC:=musleabi
|
||||
PKG_BUILD_DEPENDS:=rust/host
|
||||
|
||||
ARM_CPU_FEATURES:=$(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE))))
|
||||
ifneq ($(filter $(ARM_CPU_FEATURES),vfp vfpv2),)
|
||||
PKG_LIBC:=musleabihf
|
||||
endif
|
||||
endif
|
||||
|
||||
PKG_ARCH=$(ARCH)
|
||||
ifeq ($(ARCH),i386)
|
||||
PKG_ARCH:=i686
|
||||
endif
|
||||
|
||||
PKG_SOURCE:=aliyundrive-webdav-v$(PKG_VERSION).$(PKG_ARCH)-unknown-linux-$(PKG_LIBC).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/messense/aliyundrive-webdav/releases/download/v$(PKG_VERSION)/
|
||||
PKG_HASH:=skip
|
||||
RUST_PKG_FEATURES:=rustls-tls atomic64 native-tls native-tls-vendored
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include ../../lang/rust/rust-package.mk
|
||||
|
||||
define Package/aliyundrive-webdav
|
||||
SECTION:=multimedia
|
||||
CATEGORY:=Multimedia
|
||||
TITLE:=WebDAV server for AliyunDrive
|
||||
URL:=https://github.com/messense/aliyundrive-webdav
|
||||
DEPENDS:=$$(RUST_ARCH_DEPENDS)
|
||||
endef
|
||||
|
||||
define Package/aliyundrive-webdav/description
|
||||
@@ -43,34 +41,14 @@ define Package/aliyundrive-webdav/conffiles
|
||||
/etc/config/aliyundrive-webdav
|
||||
endef
|
||||
|
||||
define Download/sha256sum
|
||||
FILE:=$(PKG_SOURCE).sha256
|
||||
URL_FILE:=$(FILE)
|
||||
URL:=$(PKG_SOURCE_URL)
|
||||
HASH:=skip
|
||||
endef
|
||||
$(eval $(call Download,sha256sum))
|
||||
|
||||
define Build/Prepare
|
||||
mv $(DL_DIR)/$(PKG_SOURCE).sha256 .
|
||||
cp $(DL_DIR)/$(PKG_SOURCE) .
|
||||
shasum -a 256 -c $(PKG_SOURCE).sha256
|
||||
rm $(PKG_SOURCE).sha256 $(PKG_SOURCE)
|
||||
|
||||
tar -C $(PKG_BUILD_DIR)/ -zxf $(DL_DIR)/$(PKG_SOURCE)
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
echo "aliyundrive-webdav using precompiled binary."
|
||||
endef
|
||||
|
||||
define Package/aliyundrive-webdav/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/aliyundrive-webdav $(1)/usr/bin/aliyundrive-webdav
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/target/$(RUSTC_TARGET_ARCH)/release/aliyundrive-webdav $(1)/usr/bin/
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/aliyundrive-webdav.init $(1)/etc/init.d/aliyundrive-webdav
|
||||
$(INSTALL_BIN) $(CURDIR)/files/aliyundrive-webdav.init $(1)/etc/init.d/aliyundrive-webdav
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./files/aliyundrive-webdav.config $(1)/etc/config/aliyundrive-webdav
|
||||
$(INSTALL_CONF) $(CURDIR)/files/aliyundrive-webdav.config $(1)/etc/config/aliyundrive-webdav
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,aliyundrive-webdav))
|
||||
+14
-16
@@ -6,32 +6,27 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=CloudDrive2
|
||||
PKG_VERSION:=0.8.16
|
||||
PKG_NAME:=clouddrive2
|
||||
PKG_VERSION:=1.0.4
|
||||
PKG_RELEASE=1
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
PKG_ARCH:=x86_64
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),aarch64)
|
||||
PKG_ARCH:=aarch64
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),arm)
|
||||
PKG_HASH:=dc9088789e75a6b17f55ea7756d841c7e660951f1195cd858c04d3d5b33ea7e0
|
||||
else ifeq ($(ARCH),arm)
|
||||
PKG_ARCH:=armv7
|
||||
PKG_HASH:=26e15f9a97bba7344f39c06e54e42232b1518293d71570f3a2a01187044cb7b5
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
PKG_ARCH:=x86_64
|
||||
PKG_HASH:=84385139ff87a038677e016d78df43669f4a07c616f0e26d90c2c9df66467af4
|
||||
endif
|
||||
|
||||
PKG_SOURCE:=clouddrive-2-linux-$(PKG_ARCH)-$(PKG_VERSION).tgz
|
||||
PKG_SOURCE_URL:=https://github.com/cloud-fs/cloud-fs.github.io/releases/download/v$(PKG_VERSION)
|
||||
PKG_HASH:=skip
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/clouddrive2
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
DEPENDS:=@(arm||aarch64||x86_64) +fuse3-utils
|
||||
DEPENDS:=@(arm||aarch64||x86_64) +fuse-utils
|
||||
TITLE:=CloudDrive2
|
||||
endef
|
||||
|
||||
@@ -39,6 +34,9 @@ define Package/clouddrive2/description
|
||||
CloudDrive2 is a cloud storage mounting tool for OpenWrt.
|
||||
endef
|
||||
|
||||
PKG_SOURCE:=clouddrive-2-linux-$(PKG_ARCH)-$(PKG_VERSION).tgz
|
||||
PKG_SOURCE_URL:=https://github.com/cloud-fs/cloud-fs.github.io/releases/download/v$(PKG_VERSION)
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
tar -xzvf $(DL_DIR)/clouddrive-2-linux-$(PKG_ARCH)-$(PKG_VERSION).tgz -C $(PKG_BUILD_DIR)/ --strip-components=1
|
||||
@@ -49,9 +47,9 @@ endef
|
||||
|
||||
define Package/clouddrive2/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/clouddrive2.init $(1)/etc/init.d/clouddrive2
|
||||
$(INSTALL_BIN) $(CURDIR)/files/clouddrive2.init $(1)/etc/init.d/clouddrive2
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) ./files/clouddrive2.config $(1)/etc/config/clouddrive2
|
||||
$(INSTALL_CONF) $(CURDIR)/files/clouddrive2.config $(1)/etc/config/clouddrive2
|
||||
$(INSTALL_DIR) $(1)/usr/share/clouddrive2
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/clouddrive-2-linux-$(PKG_ARCH)-$(PKG_VERSION)/clouddrive $(1)/usr/share/clouddrive2/
|
||||
cp -rf $(PKG_BUILD_DIR)/clouddrive-2-linux-$(PKG_ARCH)-$(PKG_VERSION)/wwwroot $(1)/usr/share/clouddrive2/
|
||||
|
||||
@@ -37,5 +37,5 @@ stop_service() {
|
||||
load_config
|
||||
echo "Stopping $SERVICE"
|
||||
killall -q clouddrive
|
||||
[ -d "$mount_point" ] && fusermount3 -u "$mount_point"
|
||||
[ -d "$mount_point" ] && fusermount -u "$mount_point"
|
||||
}
|
||||
+15
-18
@@ -1,7 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
# Copyright (C) 2021-2026 sirpdboy <herboy2008@gmail.com>
|
||||
# Copyright (C) 2021-2023 sirpdboy <herboy2008@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
@@ -15,46 +17,41 @@ PKG_HASH:=05ae7ef07241113ee2cd861be530524f06856fc7368b84846db5137a477277ea
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=sirpdboy <herboy2008@gmail.com>
|
||||
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||
|
||||
PKG_BUILD_DEPENDS:=golang/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_BUILD_FLAGS:=no-mips16
|
||||
|
||||
GO_PKG:=github.com/jeessy2/ddns-go/v6
|
||||
GO_PKG_LDFLAGS_X:=main.Version=$(PKG_VERSION)
|
||||
GO_PKG_LDFLAGS:=$(GO_PKG_LDFLAGS_X)
|
||||
GO_PKG_LDFLAGS_X:=main.version=$(PKG_VERSION)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||
|
||||
define Package/ddns-go
|
||||
TITLE:=A Linux web GUI client of ddns-go
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=IP Addresses and Names
|
||||
TITLE:=Support IPV4 and IPV6 simple and easy-to-use IP binding domain name tool
|
||||
URL:=https://github.com/jeessy2/ddns-go
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle
|
||||
URL:=https://github.com/jeessy2/ddns-go
|
||||
USERID:=ddns-go:ddns-go
|
||||
endef
|
||||
|
||||
define Package/ddns-go/description
|
||||
A simple and easy-to-use IP binding domain name tool that supports IPV4 and IPV6.
|
||||
ddns-go is a automatically obtain your public IPv4 or IPv6 address and resolve it to the corresponding domain name service,
|
||||
support Alidns Dnspod Cloudflare Hicloud Callback Baiducloud porkbun GoDaddy Google Domains.
|
||||
endef
|
||||
|
||||
define Package/ddns-go/conffiles
|
||||
/etc/config/ddns-go
|
||||
/etc/ddns-go/ddns-go-config.yaml
|
||||
endef
|
||||
|
||||
|
||||
define Package/ddns-go/install
|
||||
$(call GoPackage/Package/Install/Bin,$(1))
|
||||
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_BIN) $(CURDIR)/files/ddns-go.init $(1)/etc/init.d/ddns-go
|
||||
$(INSTALL_CONF) $(CURDIR)/files/ddns-go.conf $(1)/etc/config/ddns-go
|
||||
$(INSTALL_BIN) $(CURDIR)/file/ddns-go.init $(1)/etc/init.d/ddns-go
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) $(CURDIR)/file/luci-ddns-go.uci-default $(1)/etc/uci-defaults/luci-ddns-go
|
||||
endef
|
||||
|
||||
$(eval $(call GoBinPackage,ddns-go))
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2021-2023 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-ddns-go
|
||||
#
|
||||
# This file is part of ddns-go .
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
|
||||
PROG=/usr/bin/ddns-go
|
||||
CONFDIR=/etc/ddns-go
|
||||
CONF=$CONFDIR/ddns-go-config.yaml
|
||||
|
||||
get_config() {
|
||||
config_get_bool enabled $1 enabled 1
|
||||
config_get_bool logger $1 logger 1
|
||||
config_get port $1 port 9876
|
||||
config_get time $1 time 300
|
||||
}
|
||||
|
||||
init_yaml(){
|
||||
[ -d $CONFDIR ] || mkdir -p $CONFDIR 2>/dev/null
|
||||
cat /usr/share/ddns-go/ddns-go-default.yaml > $CONF
|
||||
}
|
||||
|
||||
start_service() {
|
||||
config_load ddns-go
|
||||
config_foreach get_config basic
|
||||
[ x$enabled == x1 ] || return 1
|
||||
[ -s ${CONF} ] || init_yaml
|
||||
logger -t ddns-go -p warn "ddns-go is start."
|
||||
echo "ddns-go is start."
|
||||
procd_open_instance
|
||||
procd_set_param command $PROG -l :$port -f $time -c "$CONF"
|
||||
[ "x$logger" == x1 ] && procd_set_param stderr 1
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "ddns-go"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -s "/etc/ddns-go/localtime" ] && mv -f /etc/ddns-go/localtime /etc/localtime
|
||||
/etc/init.d/ddns-go enable
|
||||
/etc/init.d/ddns-go start
|
||||
rm -f /tmp/luci*
|
||||
exit 0
|
||||
@@ -1,9 +0,0 @@
|
||||
config basic 'config'
|
||||
option enabled '0'
|
||||
option logger '1'
|
||||
option port '9876'
|
||||
option time '300'
|
||||
option ctimes '5'
|
||||
option skipverify '0'
|
||||
option delay '0'
|
||||
option dns '223.5.5.5'
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2021-2026 sirpdboy <herboy2008@gmail.com>
|
||||
#
|
||||
# This file is part of ddns-go .
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
NAME=ddns-go
|
||||
PROG=/usr/bin/ddns-go
|
||||
CONFDIR=/etc/ddns-go
|
||||
CONF=$CONFDIR/ddns-go-config.yaml
|
||||
|
||||
init_yaml() {
|
||||
[ -d "$CONFDIR" ] || mkdir -p "$CONFDIR"
|
||||
chown -R ddns-go:ddns-go "$CONFDIR"
|
||||
chmod 755 "$CONFDIR"
|
||||
[ -f "$CONF" ] && chmod 644 "$CONF"
|
||||
}
|
||||
|
||||
build_args() {
|
||||
local cfg="$1"
|
||||
local args="-c $CONF"
|
||||
|
||||
config_get port "$cfg" port '9876'
|
||||
args="$args -l :$port"
|
||||
|
||||
config_get time "$cfg" time '300'
|
||||
[ -n "$time" ] && args="$args -f $time"
|
||||
|
||||
config_get ctimes "$cfg" ctimes '5'
|
||||
[ -n "$ctimes" ] && args="$args -cacheTimes $ctimes"
|
||||
|
||||
config_get dns "$cfg" dns '223.5.5.5'
|
||||
[ -n "$dns" ] && args="$args -dns $dns"
|
||||
|
||||
config_get_bool noweb "$cfg" noweb 0
|
||||
[ "$noweb" -eq 1 ] && args="$args -noweb"
|
||||
|
||||
config_get_bool skipverify "$cfg" skipverify 0
|
||||
[ "$skipverify" -eq 1 ] && args="$args -skipVerify"
|
||||
|
||||
echo "$args"
|
||||
}
|
||||
|
||||
start_instance() {
|
||||
local cfg="$1"
|
||||
config_get_bool enabled "$cfg" enabled 0
|
||||
[ "$enabled" -eq 0 ] && return 0
|
||||
|
||||
config_get delay "$cfg" delay 0
|
||||
if [ "$delay" -gt 0 ]; then
|
||||
local uptime=$(awk -F. '{print $1}' /proc/uptime)
|
||||
[ "$uptime" -lt 120 ] && sleep "$delay"
|
||||
fi
|
||||
|
||||
init_yaml
|
||||
|
||||
local args=$(build_args "$cfg")
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command $PROG $args
|
||||
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_set_param log_level 7
|
||||
|
||||
procd_set_param user ddns-go
|
||||
procd_set_param respawn
|
||||
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
start_service() {
|
||||
config_load "$NAME"
|
||||
config_foreach start_instance 'basic'
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$NAME"
|
||||
}
|
||||
+45
-40
@@ -1,63 +1,68 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
# Copyright (C) 2017-2024
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
#
|
||||
# Copyright (C) 2024 op.dllkids.xyz
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=filebrowser
|
||||
PKG_VERSION:=0.8.7-beta
|
||||
PKG_RELEASE=1
|
||||
PKG_VERSION:=2.63.18
|
||||
PKG_RELEASE:=1
|
||||
|
||||
ifeq ($(ARCH),aarch64)
|
||||
PKG_ARCH:=arm64
|
||||
PKG_HASH:=skip
|
||||
else ifeq ($(ARCH),arm)
|
||||
PKG_ARCH:=armv7
|
||||
PKG_HASH:=skip
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
PKG_ARCH:=amd64
|
||||
PKG_HASH:=skip
|
||||
endif
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/filebrowser/filebrowser/tar.gz/v${PKG_VERSION}?
|
||||
PKG_HASH:=b665942fa4adb882498e89f09ef90f4690de4f22de043453c28e201c812060c5
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=kenzo <kenzok8@gmail.com>
|
||||
|
||||
PKG_BUILD_DEPENDS:=golang/host node/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_BUILD_FLAGS:=no-mips16
|
||||
|
||||
GO_PKG:=github.com/filebrowser/filebrowser
|
||||
GO_PKG_LDFLAGS_X:= \
|
||||
$(GO_PKG)/v2/version.CommitSHA=$(PKG_SOURCE_VERSION) \
|
||||
$(GO_PKG)/v2/version.Version=v$(PKG_VERSION)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||
|
||||
define Package/filebrowser
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
DEPENDS:=@(arm||aarch64||x86_64)
|
||||
TITLE:=FileBrowser Quantum
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Web File Browser
|
||||
URL:=https://github.com/filebrowser/filebrowser
|
||||
DEPENDS:=$(GO_ARCH_DEPENDS)
|
||||
endef
|
||||
|
||||
define Package/filebrowser/description
|
||||
The best free self-hosted web-based file manager.
|
||||
endef
|
||||
|
||||
PKG_SOURCE:=linux-$(PKG_ARCH)-filebrowser
|
||||
PKG_SOURCE_URL:=https://github.com/gtsteffaniak/filebrowser/releases/download/v$(PKG_VERSION)
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
filebrowser provides a file managing interface within a specified directory
|
||||
and it can be used to upload, delete, preview, rename and edit your files.
|
||||
It allows the creation of multiple users and each user can have its own directory.
|
||||
It can be used as a standalone app or as a middleware.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/filebrowser/conffiles
|
||||
/etc/filebrowser/
|
||||
/etc/config/filebrowser
|
||||
( \
|
||||
pushd "$(PKG_BUILD_DIR)/frontend" ; \
|
||||
npm install -g pnpm ; \
|
||||
pnpm install --frozen-lockfile ; \
|
||||
pnpm run build ; \
|
||||
popd ; \
|
||||
$(call GoPackage/Build/Compile) ; \
|
||||
)
|
||||
endef
|
||||
|
||||
define Package/filebrowser/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) $(CURDIR)/files/filebrowser.init $(1)/etc/init.d/filebrowser
|
||||
$(call GoPackage/Package/Install/Bin,$(1))
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_CONF) $(CURDIR)/files/filebrowser.config $(1)/etc/config/filebrowser
|
||||
$(INSTALL_DIR) $(1)/etc/filebrowser
|
||||
$(INSTALL_CONF) $(CURDIR)/files/config.yaml $(1)/etc/filebrowser/config.yaml
|
||||
$(INSTALL_DIR) $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(DL_DIR)/linux-$(PKG_ARCH)-filebrowser $(1)/usr/bin/filebrowser
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) $(CURDIR)/files/filebrowser.init $(1)/etc/init.d/filebrowser
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,filebrowser))
|
||||
$(eval $(call GoBinPackage,filebrowser))
|
||||
$(eval $(call BuildPackage,filebrowser))
|
||||
@@ -1,156 +0,0 @@
|
||||
server:
|
||||
minSearchLength: 3 # minimum length of search query to begin searching (default: 3)
|
||||
disableUpdateCheck: false # disables backend update check service
|
||||
numImageProcessors: 4 # number of concurrent image processing jobs used to create previews, default is number of cpu cores available.
|
||||
socket: "" # socket to listen on
|
||||
tlsKey: "" # path to TLS key
|
||||
tlsCert: "" # path to TLS cert
|
||||
disablePreviews: false # disable all previews thumbnails, simple icons will be used
|
||||
disablePreviewResize: false # disable resizing of previews for faster loading over slow connections
|
||||
disableTypeDetectionByHeader: false # disable type detection by header, useful if filesystem is slow.
|
||||
port: 8989
|
||||
baseURL: "/"
|
||||
logging:
|
||||
- levels: "" # separated list of log levels to enable. (eg. "info|warning|error|debug")
|
||||
apiLevels: "" # separated list of log levels to enable for the API. (eg. "info|warning|error")
|
||||
output: "stdout" # output location. (eg. "stdout" or "path/to/file.log")
|
||||
noColors: false # disable colors in the output
|
||||
json: false # output in json format
|
||||
utc: false # use UTC time in the output instead of local time
|
||||
debugMedia: false # output ffmpeg stdout for media integration -- careful can produces lots of output!
|
||||
database: "/etc/filebrowser/database.db" # path to the database file
|
||||
sources: # validate:required,dive
|
||||
- path: "/"
|
||||
name: "Root" # display name
|
||||
config:
|
||||
denyByDefault: false # deny access unless an "allow" access rule was specifically created.
|
||||
private: false # designate as source as private -- currently just means no sharing permitted.
|
||||
disabled: false # disable the source, this is useful so you don't need to remove it from the config file
|
||||
indexingIntervalMinutes: 0 # optional manual overide interval in minutes to re-index the source
|
||||
disableIndexing: false # disable the indexing of this source
|
||||
maxWatchers: 0 # number of concurrent watchers to use for this source, currently not supported
|
||||
neverWatchPaths: []
|
||||
exclude: # exclude files and folders from indexing, if include is not set
|
||||
hidden: false # exclude hidden files and folders.
|
||||
ignoreZeroSizeFolders: false # ignore folders with 0 size
|
||||
filePaths: []
|
||||
folderPaths: []
|
||||
fileNames: []
|
||||
folderNames: []
|
||||
fileEndsWith: []
|
||||
folderEndsWith: []
|
||||
fileStartsWith: []
|
||||
folderStartsWith: []
|
||||
include: # include files and folders from indexing, if exclude is not set
|
||||
rootFolders: []
|
||||
rootFiles: []
|
||||
defaultUserScope: "/" # default "/" should match folders under path
|
||||
defaultEnabled: false # should be added as a default source for new users?
|
||||
createUserDir: false # create a user directory for each user
|
||||
externalUrl: "" # used by share links if set (eg. http://mydomain.com)
|
||||
internalUrl: "" # used by integrations if set, this is the base domain that an integration service will use to communicate with filebrowser (eg. http://localhost:8080)
|
||||
cacheDir: "tmp" # path to the cache directory, used for thumbnails and other cached files
|
||||
maxArchiveSize: 50 # max pre-archive combined size of files/folder that are allowed to be archived (in GB)
|
||||
auth:
|
||||
tokenExpirationHours: 2 # time in hours each web UI session token is valid for. Default is 2 hours.
|
||||
methods:
|
||||
proxy: # validate:omitempty
|
||||
enabled: false
|
||||
createUser: false # create user if not exists
|
||||
header: "" # required header to use for authentication. Security Warning: FileBrowser blindly accepts the header value as username.
|
||||
logoutRedirectUrl: "" # if provider logout url is provided, filebrowser will also redirect to logout url. Custom logout query params are respected.
|
||||
noauth: false # if set to true, overrides all other auth methods and disables authentication
|
||||
password: # validate:omitempty
|
||||
enabled: true
|
||||
minLength: 3 # minimum pasword length required, default is 5. validate:omitempty
|
||||
signup: false # allow signups on login page if enabled -- not secure. validate:omitempty
|
||||
recaptcha: # recaptcha config, only used if signup is enabled validate:omitempty
|
||||
host: "" # validate:required
|
||||
key: "" # validate:required
|
||||
secret: "" # validate:required
|
||||
enforcedOtp: false # if set to true, TOTP is enforced for all password users users. Otherwise, users can choose to enable TOTP.
|
||||
oidc: # validate:omitempty
|
||||
enabled: false # whether to enable OIDC authentication
|
||||
clientId: "**hidden**" # secret: client id of the OIDC application
|
||||
clientSecret: "**hidden**" # secret: client secret of the OIDC application
|
||||
issuerUrl: "" # authorization URL of the OIDC provider
|
||||
scopes: "openid email profile" # scopes to request from the OIDC provider
|
||||
userIdentifier: "preferred_username" # the field value to use as the username. Default is "preferred_username", can also be "email" or "username", or "phone"
|
||||
disableVerifyTLS: false # disable TLS verification for the OIDC provider. This is insecure and should only be used for testing.
|
||||
logoutRedirectUrl: "" # if provider logout url is provided, filebrowser will also redirect to logout url. Custom logout query params are respected.
|
||||
createUser: false # create user if not exists
|
||||
adminGroup: "" # if set, users in this group will be granted admin privileges.
|
||||
groupsClaim: "groups" # the JSON field name to read groups from. Default is "groups"
|
||||
key: "**hidden**" # secret: the key used to sign the JWT tokens. If not set, a random key will be generated.
|
||||
adminUsername: "admin" # secret: the username of the admin user. If not set, the default is "admin".
|
||||
adminPassword: "admin" # secret: the password of the admin user. If not set, the default is "admin".
|
||||
totpSecret: "**hidden**" # secret: secret used to encrypt TOTP secrets
|
||||
frontend:
|
||||
name: "FileBrowser Quantum" # display name
|
||||
disableDefaultLinks: false # disable default links in the sidebar
|
||||
disableUsedPercentage: false # disable used percentage for the sources in the sidebar
|
||||
externalLinks:
|
||||
- text: "Help" # the text to display on the link validate:required
|
||||
title: "" # the title to display on hover
|
||||
url: "https://github.com/gtsteffaniak/filebrowser" # the url to link to validate:required
|
||||
disableNavButtons: false # disable the nav buttons in the sidebar
|
||||
styling:
|
||||
customCSS: "" # if a valid path to a css file is provided, it will be applied for all users. (eg. "reduce-rounded-corners.css")
|
||||
lightBackground: "#f5f5f5" # specify a valid CSS color property value to use as the background color in light mode
|
||||
darkBackground: "#141D24" # Specify a valid CSS color property value to use as the background color in dark mode
|
||||
customThemes: # A list of custom css files that each user can select to override the default styling. if "default" is key name then it will be the default option.
|
||||
default:
|
||||
description: "The default theme" # The description of the theme to display in the UI.
|
||||
css: "" # The css file path and filename to use for the theme.
|
||||
alternative:
|
||||
description: "Reduce rounded corners" # The description of the theme to display in the UI.
|
||||
css: "reduce-rounded-corners.css" # The css file path and filename to use for the theme.
|
||||
favicon: "" # path to a favicon to use for the frontend
|
||||
description: "FileBrowser Quantum is a file manager for the web which can be used to manage files on your server" # description that shows up in html head meta description
|
||||
userDefaults:
|
||||
editorQuickSave: false # show quick save button in editor
|
||||
hideSidebarFileActions: false # hide the file actions in the sidebar
|
||||
disableQuickToggles: false # disable the quick toggles in the sidebar
|
||||
disableSearchOptions: false # disable the search options in the search bar
|
||||
stickySidebar: true # keep sidebar open when navigating
|
||||
darkMode: true # should dark mode be enabled
|
||||
locale: "zhCN" # language to use: eg. de, en, or fr
|
||||
viewMode: "normal" # view mode to use: eg. normal, list, grid, or compact
|
||||
singleClick: false # open directory on single click, also enables middle click to open in new tab
|
||||
showHidden: false # show hidden files in the UI. On windows this includes files starting with a dot and windows hidden files
|
||||
dateFormat: false # when false, the date is relative, when true, the date is an exact timestamp
|
||||
gallerySize: 3 # 0-9 - the size of the gallery thumbnails
|
||||
themeColor: "var(--blue)" # theme color to use: eg. #ff0000, or var(--red), var(--purple), etc
|
||||
quickDownload: false # show icon to download in one click
|
||||
disablePreviewExt: "" # space separated list of file extensions to disable preview for
|
||||
disableViewingExt: "" # space separated list of file extensions to disable viewing for
|
||||
lockPassword: false # disable the user from changing their password
|
||||
disableSettings: false # disable the user from viewing the settings page
|
||||
preview:
|
||||
disableHideSidebar: false
|
||||
highQuality: false
|
||||
image: false
|
||||
video: false
|
||||
motionVideoPreview: false
|
||||
office: false
|
||||
popup: false
|
||||
autoplayMedia: false
|
||||
defaultMediaPlayer: false
|
||||
folder: false
|
||||
permissions:
|
||||
api: false
|
||||
admin: false
|
||||
modify: false
|
||||
share: false
|
||||
realtime: false
|
||||
loginMethod: "password" # login method to use: eg. password, proxy, oidc
|
||||
disableUpdateNotifications: false # disable update notifications banner for admin users
|
||||
deleteWithoutConfirming: false # delete files without confirmation
|
||||
fileLoading: # upload and download settings
|
||||
maxConcurrentUpload: 10
|
||||
uploadChunkSizeMb: 10
|
||||
clearAll: false
|
||||
disableOnlyOfficeExt: "" # list of file extensions to disable onlyoffice editor for
|
||||
customTheme: "" # Name of theme to use chosen from custom themes config.
|
||||
showSelectMultiple: false # show select multiple files on desktop
|
||||
debugOffice: false # debug onlyoffice editor
|
||||
@@ -1,7 +1,9 @@
|
||||
|
||||
config filebrowser 'config'
|
||||
option addr_type 'lan'
|
||||
option db_dir '/etc'
|
||||
option db_name 'filebrowser.db'
|
||||
option enabled '0'
|
||||
option listen_port '8989'
|
||||
option root_path '/'
|
||||
option base_url '/'
|
||||
option disable_exec '1'
|
||||
option port '8989'
|
||||
option root_dir '/'
|
||||
|
||||
Regular → Executable
+24
-21
@@ -1,31 +1,34 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2021 ImmortalWrt
|
||||
|
||||
START=99
|
||||
START=90
|
||||
STOP=10
|
||||
|
||||
CONF="filebrowser"
|
||||
PROG="/usr/bin/filebrowser"
|
||||
CONF_PATH="/etc/filebrowser/config.yaml"
|
||||
PID_FILE="/var/run/filebrowser.pid"
|
||||
addr_type="$(uci get filebrowser.config.addr_type)"
|
||||
db_dir="$(uci get filebrowser.config.db_dir)"
|
||||
[ "${db_dir}" == "/" ] || db_dir="${db_dir%*/}"
|
||||
db_name="$(uci get filebrowser.config.db_name| sed 's#/##g')"
|
||||
enabled="$(uci get filebrowser.config.enabled)"
|
||||
port="$(uci get filebrowser.config.port)"
|
||||
root_dir="$(uci get filebrowser.config.root_dir)"
|
||||
|
||||
if [ "${addr_type}" == "local" ];then
|
||||
addr="127.0.0.1"
|
||||
elif [ "${addr_type}" == "lan" ];then
|
||||
addr="$(uci get network.lan.ipaddr)"
|
||||
elif [ "${addr_type}" == "wan" ];then
|
||||
addr="0.0.0.0"
|
||||
fi
|
||||
|
||||
start() {
|
||||
config_load "$CONF"
|
||||
|
||||
local enabled
|
||||
config_get_bool enabled "config" "enabled" "0"
|
||||
[ "$enabled" -eq "1" ] || return 1
|
||||
|
||||
local listen_port root_path base_url
|
||||
config_get listen_port "config" "listen_port" "8989"
|
||||
config_get root_path "config" "root_path" "/"
|
||||
config_get base_url "config" "base_url" "/"
|
||||
|
||||
echo "Starting filebrowser..."
|
||||
start-stop-daemon -S -q -b -m -p "$PID_FILE" -x "$PROG" -- -c "$CONF_PATH"
|
||||
stop
|
||||
[ "$enabled" == "1" ] || exit 0
|
||||
mkdir -p "${root_dir}"
|
||||
mkdir -p "${db_dir}"
|
||||
filebrowser -a "${addr}" -d "${db_dir}/${db_name}" -p "${port}" -r "${root_dir}" >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
stop() {
|
||||
kill -9 `pidof filebrowser | sed "s/$$//g"` 2>/dev/null
|
||||
rm -f "$PID_FILE"
|
||||
echo "filebrowser stopped"
|
||||
echo "${db_dir}/${db_name}" > "/lib/upgrade/keep.d/filebrowser"
|
||||
killall -3 filebrowser >/dev/null 2>&1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for UUgamebooster
|
||||
LUCI_DEPENDS:=+uugamebooster
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require view';
|
||||
'require poll';
|
||||
'require ui';
|
||||
'require rpc';
|
||||
|
||||
var callServiceList = rpc.declare({
|
||||
object: 'service',
|
||||
method: 'list',
|
||||
params: ['name'],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
function getServiceStatus() {
|
||||
return L.resolveDefault(callServiceList('uugamebooster'), {}).then(function(res) {
|
||||
var instances = res['uugamebooster'] && res['uugamebooster']['instances'];
|
||||
if (instances) {
|
||||
for (var key in instances) {
|
||||
if (instances[key] && instances[key].running)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
render: function() {
|
||||
var m, s, o;
|
||||
|
||||
m = new form.Map('uugamebooster', _('UU Game Accelerator'), _('A Paid Game Acceleration service'));
|
||||
|
||||
s = m.section(form.GridSection, '_status', _('Status'));
|
||||
s.render = function() {
|
||||
return E('div', { class: 'cbi-section' }, [
|
||||
E('p', { id: 'uugamebooster_status' }, _('Collecting data...'))
|
||||
]);
|
||||
};
|
||||
|
||||
s = m.section(form.TypedSection, 'uugamebooster', _('Settings'));
|
||||
s.anonymous = true;
|
||||
s.addremove = false;
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enable'));
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
|
||||
s = m.section(form.GridSection, '_qrcode', _('QR Code'));
|
||||
s.render = function() {
|
||||
return E('div', { class: 'cbi-section' }, [
|
||||
E('p', { id: 'uugamebooster_qcode' }, [
|
||||
E('img', { src: '/uugamebooster/uuios.png', height: '300' }),
|
||||
E('img', { src: '/uugamebooster/uuandriod.png', height: '300' })
|
||||
])
|
||||
]);
|
||||
};
|
||||
|
||||
poll.add(function() {
|
||||
return getServiceStatus().then(function(running) {
|
||||
var node = document.getElementById('uugamebooster_status');
|
||||
if (node) {
|
||||
if (running) {
|
||||
node.innerHTML = '<em><b><font color="green">UU GameAcc ' + _('RUNNING') + '</font></b></em>';
|
||||
} else {
|
||||
node.innerHTML = '<em><b><font color="red">UU GameAcc ' + _('NOT RUNNING') + '</font></b></em>';
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 3);
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"Language: zh_Hans\n"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:24
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
#: root/usr/share/luci/menu.d/luci-app-uugamebooster.json:3
|
||||
msgid "UU GameAcc"
|
||||
msgstr "UU游戏加速器"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:11
|
||||
msgid "UU Game Accelerator"
|
||||
msgstr "UU游戏加速器"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:11
|
||||
msgid "A Paid Game Acceleration service"
|
||||
msgstr "一个付费主机游戏加速器 (开启服务后,使用手机APP绑定路由器并指定加速主机)"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:13
|
||||
msgid "Status"
|
||||
msgstr "状态"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:16
|
||||
msgid "Collecting data..."
|
||||
msgstr "正在收集数据..."
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:20
|
||||
msgid "Settings"
|
||||
msgstr "设置"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:28
|
||||
msgid "QR Code"
|
||||
msgstr "二维码"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:44
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
|
||||
#: htdocs/luci-static/resources/view/uugamebooster.js:46
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"admin/services/uugamebooster": {
|
||||
"title": "UU GameAcc",
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "uugamebooster"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-uugamebooster" ],
|
||||
"uci": { "uugamebooster": true }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"luci-app-uugamebooster": {
|
||||
"description": "Grant UCI access for luci-app-uugamebooster",
|
||||
"read": {
|
||||
"uci": [ "uugamebooster" ],
|
||||
"ubus": {
|
||||
"service": [ "list" ]
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "uugamebooster" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
+6
-20
@@ -1,10 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
# Copyright (C) 2021-2025 sirpdboy <herboy2008@gmail.com>
|
||||
# Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
@@ -26,12 +25,8 @@ ifeq ($(ARCH),x86_64)
|
||||
LUCKY_ARCH:=x86_64
|
||||
endif
|
||||
ifeq ($(ARCH),arm)
|
||||
ifeq ($(BOARD),bcm53xx)
|
||||
LUCKY_ARCH:=armv6
|
||||
else
|
||||
LUCKY_ARCH:=armv7
|
||||
endif
|
||||
endif
|
||||
ifeq ($(BOARD),bcm53xx)
|
||||
LUCKY_ARCH:=armv6
|
||||
ifeq ($(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE)))),)
|
||||
@@ -50,42 +45,33 @@ PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=GDY666 <gdy666@foxmail.com>
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_HASH:=skip
|
||||
PKG_HASH:=0216c9a833724875f4a004aa5fc5e6e1a2d9f92f99e933905f76ebf7876b413c
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Lucky gdy
|
||||
TITLE:=Lucky dynamic domain name ddns-go service, socat,frp
|
||||
DEPENDS:=@(i386||x86_64||arm||aarch64||mipsel||mips)
|
||||
URL:=https://github.com/gdy666/lucky
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
Main functions of Lucky: ipv4/ipv6 portforward,ddns,IOT wake on lan ,reverse proxy and more...
|
||||
Main functions of Lucky: dynamic domain name ddns-go service, socat,reverse proxy ,wake on lan
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
[ ! -f $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz ] && wget https://github.com/gdy666/lucky/releases/download/v$(PKG_VERSION)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -O $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz
|
||||
tar -xzvf $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -C $(PKG_BUILD_DIR) || exit 1
|
||||
tar -xzvf $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -C $(PKG_BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/conffiles
|
||||
/etc/config/lucky
|
||||
/etc/lucky/*
|
||||
endef
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin/
|
||||
$(INSTALL_DIR) $(1)/etc/init.d/
|
||||
$(INSTALL_DIR) $(1)/etc/config/
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lucky $(1)/usr/bin/lucky
|
||||
$(INSTALL_BIN) $(CURDIR)/files/luckyarch.bin $(1)/usr/bin/luckyarch
|
||||
$(INSTALL_BIN) ./files/lucky.init $(1)/etc/init.d/lucky
|
||||
$(INSTALL_CONF) $(CURDIR)/files/lucky.config $(1)/etc/config/lucky
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
@@ -1,5 +0,0 @@
|
||||
config lucky 'lucky'
|
||||
option logger '1'
|
||||
option port '16601'
|
||||
option configdir '/etc/lucky'
|
||||
option enabled '0'
|
||||
@@ -1,81 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2021-2025 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-lucky
|
||||
|
||||
# This file is part of lucky .
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
|
||||
START=99
|
||||
STOP=15
|
||||
USE_PROCD=1
|
||||
|
||||
CONF=lucky
|
||||
PROG=/usr/bin/lucky
|
||||
CONFDIR=/etc/lucky
|
||||
|
||||
get_config() {
|
||||
config_get_bool enabled $1 enabled 0
|
||||
config_get_bool logger $1 logger 1
|
||||
config_get port $1 port 16601
|
||||
config_get SafeURL $1 safe
|
||||
config_get delay $1 delay 0
|
||||
|
||||
}
|
||||
|
||||
init_config(){
|
||||
config_load "$CONF"
|
||||
config_foreach get_config "$CONF"
|
||||
}
|
||||
|
||||
init_confdir(){
|
||||
[ -d $CONFDIR ] || mkdir -p $CONFDIR 2>/dev/null
|
||||
}
|
||||
|
||||
LOG(){
|
||||
echo "$1"
|
||||
logger -t lucky -p warn "$1"
|
||||
}
|
||||
|
||||
start_instance() {
|
||||
enabled=$(uci -q get $CONF.$CONF.enabled ) || enabled="0"
|
||||
logger=$(uci -q get $CONF.$CONF.logger ) || logger="1"
|
||||
port=$(uci -q get $CONF.$CONF.port ) || port="16601"
|
||||
SafeURL=$(uci -q get $CONF.$CONF.safe ) || SafeURL=" "
|
||||
delay=$(uci -q get $CONF.$CONF.delay ) || delay="5"
|
||||
SafeURL="${SafeURL##*( )}"
|
||||
SafeURL="${SafeURL%%*( )}"
|
||||
|
||||
init_confdir
|
||||
[ x$enabled = x1 ] || return 1
|
||||
[ $(awk -F. '{print $1}' /proc/uptime) -lt "120" ] && sleep $delay
|
||||
$(which lucky) -setconf -key AdminWebListenPort -value $port -cd $CONFDIR
|
||||
if [ -z "$SafeURL" ] ; then
|
||||
$(which lucky) -rCancelSafeURL
|
||||
else
|
||||
$(which lucky) -setconf -key SafeURL -value "$SafeURL" -cd $CONFDIR
|
||||
fi
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command $PROG
|
||||
procd_append_param command -cd $CONFDIR
|
||||
procd_set_param respawn
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
LOG "lucky is start."
|
||||
|
||||
}
|
||||
|
||||
start_service() {
|
||||
pgrep -f $PROG | xargs kill -9 >/dev/null 2>&1
|
||||
start_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
pgrep -f $PROG | xargs kill -9 >/dev/null 2>&1
|
||||
LOG "lucky is stop."
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger lucky
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
cputype=$(uname -ms | tr ' ' '_' | tr '[A-Z]' '[a-z]')
|
||||
[ -n "$(echo $cputype | grep -E "linux.*armv.*")" ] && cpucore="armv5"
|
||||
[ -n "$(echo $cputype | grep -E "linux.*armv7.*")" ] && [ -n "$(cat /proc/cpuinfo | grep vfp)" ] && [ ! -d /jffs/clash ] && cpucore="armv7"
|
||||
[ -n "$(echo $cputype | grep -E "linux.*aarch64.*|linux.*armv8.*")" ] && cpucore="arm64"
|
||||
[ -n "$(echo $cputype | grep -E "linux.*86.*")" ] && cpucore="i386"
|
||||
[ -n "$(echo $cputype | grep -E "linux.*86_64.*")" ] && cpucore="x86_64"
|
||||
if [ -n "$(echo $cputype | grep -E "linux.*mips.*")" ];then
|
||||
mipstype=$(echo -n I | hexdump -o 2>/dev/null | awk '{ print substr($2,6,1); exit}') #通过判断大小端判断mips或mipsle
|
||||
[ "$mipstype" = "0" ] && cpucore="mips_softfloat" || cpucore="mipsle_softfloat"
|
||||
fi
|
||||
|
||||
echo $cpucore
|
||||
+3
-2
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=mosdns
|
||||
PKG_VERSION:=5.3.4
|
||||
PKG_RELEASE:=6
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/IrineSistiana/mosdns/tar.gz/v$(PKG_VERSION)?
|
||||
@@ -18,10 +18,11 @@ PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||
|
||||
PKG_BUILD_DEPENDS:=golang/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_BUILD_FLAGS:=no-mips16
|
||||
|
||||
GO_PKG:=github.com/IrineSistiana/mosdns
|
||||
GO_PKG_LDFLAGS_X:=main.version=v$(PKG_VERSION)-$(PKG_RELEASE)
|
||||
GO_PKG_LDFLAGS_X:=main.version=v$(PKG_VERSION)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
From 201408484de552cb927f6a50b76a34d65c8ac8c6 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Fri, 20 Mar 2026 10:39:22 +0800
|
||||
Subject: [PATCH] mosdns: update dependencies
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
.github/workflows/release.yml | 2 +-
|
||||
.github/workflows/test.yml | 2 +-
|
||||
go.mod | 36 +++++++++----------
|
||||
go.sum | 68 +++++++++++++++++------------------
|
||||
pkg/query_context/context.go | 1 -
|
||||
5 files changed, 54 insertions(+), 55 deletions(-)
|
||||
|
||||
--- a/.github/workflows/release.yml
|
||||
+++ b/.github/workflows/release.yml
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
- go-version: "1.25"
|
||||
+ go-version: "1.26"
|
||||
check-latest: true
|
||||
cache: true
|
||||
|
||||
--- a/.github/workflows/test.yml
|
||||
+++ b/.github/workflows/test.yml
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
- go-version: "1.25"
|
||||
+ go-version: "1.26"
|
||||
check-latest: true
|
||||
cache: true
|
||||
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -1,30 +1,30 @@
|
||||
module github.com/IrineSistiana/mosdns/v5
|
||||
|
||||
-go 1.24.9
|
||||
+go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57
|
||||
- github.com/go-chi/chi/v5 v5.2.3
|
||||
- github.com/go-viper/mapstructure/v2 v2.4.0
|
||||
+ github.com/go-chi/chi/v5 v5.2.5
|
||||
+ github.com/go-viper/mapstructure/v2 v2.5.0
|
||||
github.com/google/nftables v0.3.0
|
||||
github.com/kardianos/service v1.2.4
|
||||
- github.com/klauspost/compress v1.18.2
|
||||
- github.com/miekg/dns v1.1.70
|
||||
+ github.com/klauspost/compress v1.18.4
|
||||
+ github.com/miekg/dns v1.1.72
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nadoo/ipset v0.5.0
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
- github.com/quic-go/quic-go v0.58.1
|
||||
+ github.com/quic-go/quic-go v0.59.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
go.uber.org/zap v1.27.1
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
- golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
|
||||
- golang.org/x/net v0.48.0
|
||||
- golang.org/x/sync v0.19.0
|
||||
- golang.org/x/sys v0.40.0
|
||||
- golang.org/x/time v0.14.0
|
||||
+ golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90
|
||||
+ golang.org/x/net v0.52.0
|
||||
+ golang.org/x/sync v0.20.0
|
||||
+ golang.org/x/sys v0.42.0
|
||||
+ golang.org/x/time v0.15.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
)
|
||||
|
||||
@@ -37,14 +37,14 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
- github.com/mdlayher/netlink v1.8.0 // indirect
|
||||
+ github.com/mdlayher/netlink v1.9.0 // indirect
|
||||
github.com/mdlayher/socket v0.5.1 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
- github.com/prometheus/procfs v0.19.2 // indirect
|
||||
+ github.com/prometheus/procfs v0.20.1 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
@@ -55,11 +55,11 @@ require (
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
- go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
+ go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
- golang.org/x/crypto v0.46.0 // indirect
|
||||
- golang.org/x/mod v0.32.0 // indirect
|
||||
- golang.org/x/text v0.33.0 // indirect
|
||||
- golang.org/x/tools v0.40.0 // indirect
|
||||
+ golang.org/x/crypto v0.49.0 // indirect
|
||||
+ golang.org/x/mod v0.34.0 // indirect
|
||||
+ golang.org/x/text v0.35.0 // indirect
|
||||
+ golang.org/x/tools v0.43.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
--- a/go.sum
|
||||
+++ b/go.sum
|
||||
@@ -13,10 +13,10 @@ github.com/frankban/quicktest v1.14.6 h1
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
-github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
|
||||
-github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
-github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
-github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
+github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||
+github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||
+github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
+github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/nftables v0.3.0 h1:bkyZ0cbpVeMHXOrtlFc8ISmfVqq5gPJukoYieyVmITg=
|
||||
@@ -25,20 +25,20 @@ github.com/inconshreveable/mousetrap v1.
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/kardianos/service v1.2.4 h1:XNlGtZOYNx2u91urOdg/Kfmc+gfmuIo1Dd3rEi2OgBk=
|
||||
github.com/kardianos/service v1.2.4/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc=
|
||||
-github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
-github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
+github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||
+github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
-github.com/mdlayher/netlink v1.8.0 h1:e7XNIYJKD7hUct3Px04RuIGJbBxy1/c4nX7D5YyvvlM=
|
||||
-github.com/mdlayher/netlink v1.8.0/go.mod h1:UhgKXUlDQhzb09DrCl2GuRNEglHmhYoWAHid9HK3594=
|
||||
+github.com/mdlayher/netlink v1.9.0 h1:G8+GLq2x3v4D4MVIqDdNUhTUC7TKiCy/6MDkmItfKco=
|
||||
+github.com/mdlayher/netlink v1.9.0/go.mod h1:YBnl5BXsCoRuwBjKKlZ+aYmEoq0r12FDA/3JC+94KDg=
|
||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
-github.com/miekg/dns v1.1.70 h1:DZ4u2AV35VJxdD9Fo9fIWm119BsQL5cZU1cQ9s0LkqA=
|
||||
-github.com/miekg/dns v1.1.70/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
|
||||
+github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
|
||||
+github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
@@ -53,12 +53,12 @@ github.com/prometheus/client_model v0.6.
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
-github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
-github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
+github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc=
|
||||
+github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
-github.com/quic-go/quic-go v0.58.1 h1:J0s55TVauDbnCEY5tU2B8e7nYb3gnKMSez5Fwi1dl2s=
|
||||
-github.com/quic-go/quic-go v0.58.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
+github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||
+github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
@@ -91,32 +91,32 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSx
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
-go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
-go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
+go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
+go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
-golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
-golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
-golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
||||
-golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
||||
-golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
-golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
-golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
-golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
-golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
-golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
+golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
+golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
+golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 h1:jiDhWWeC7jfWqR9c/uplMOqJ0sbNlNWv0UkzE0vX1MA=
|
||||
+golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90/go.mod h1:xE1HEv6b+1SCZ5/uscMRjUBKtIxworgEcEi+/n9NQDQ=
|
||||
+golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
|
||||
+golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
|
||||
+golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
+golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
+golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
+golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
-golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
-golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
-golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
-golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
-golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
-golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
-golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
-golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
+golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
+golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
+golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
+golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
+golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
+golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
|
||||
+golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
--- a/pkg/query_context/context.go
|
||||
+++ b/pkg/query_context/context.go
|
||||
@@ -108,7 +108,6 @@ func (ctx *Context) QQuestion() dns.Ques
|
||||
// It's a helper func for searching opt in Q() manually.
|
||||
func (ctx *Context) QOpt() *dns.OPT {
|
||||
opt := findOpt(ctx.query)
|
||||
- ctx.query.IsEdns0()
|
||||
if opt == nil {
|
||||
panic("query opt is missing")
|
||||
}
|
||||
@@ -9,7 +9,7 @@ Subject: [PATCH 3/5] add response for bad request in ServeHTTP handler
|
||||
|
||||
--- a/pkg/server/http_handler.go
|
||||
+++ b/pkg/server/http_handler.go
|
||||
@@ -91,6 +91,7 @@ func (h *HttpHandler) ServeHTTP(w http.R
|
||||
@@ -93,6 +93,7 @@ func (h *HttpHandler) ServeHTTP(w http.R
|
||||
if err != nil {
|
||||
h.warnErr(req, "invalid request", err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
|
||||
@@ -1,697 +0,0 @@
|
||||
From 9554c5b29aff4107504bdf45c35582e6d9743a93 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Mon, 20 Apr 2026 23:06:17 +0800
|
||||
Subject: [PATCH] add auto-reload rule files on modification
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
pkg/utils/file_watcher.go | 73 +++++++++++++++
|
||||
plugin/data_provider/domain_set/domain_set.go | 71 +++++++++++---
|
||||
plugin/data_provider/ip_set/ip_set.go | 75 +++++++++++----
|
||||
plugin/executable/arbitrary/arbitrary.go | 81 +++++++++++-----
|
||||
plugin/executable/hosts/hosts.go | 87 ++++++++++++-----
|
||||
plugin/executable/redirect/redirect.go | 93 +++++++++++++------
|
||||
6 files changed, 374 insertions(+), 106 deletions(-)
|
||||
create mode 100644 pkg/utils/file_watcher.go
|
||||
|
||||
--- /dev/null
|
||||
+++ b/pkg/utils/file_watcher.go
|
||||
@@ -0,0 +1,73 @@
|
||||
+package utils
|
||||
+
|
||||
+import (
|
||||
+ "os"
|
||||
+ "time"
|
||||
+)
|
||||
+
|
||||
+// FileWatcher periodically checks the modification time of the specified files.
|
||||
+type FileWatcher struct {
|
||||
+ done chan struct{}
|
||||
+}
|
||||
+
|
||||
+// StartFileWatcher starts a new FileWatcher that checks files every 'interval'.
|
||||
+// If any file modification time changes or a file is missing, onChange is triggered.
|
||||
+// Note: onChange must be safe to run concurrently with other components.
|
||||
+func StartFileWatcher(files []string, interval time.Duration, onChange func(changedFiles []string)) *FileWatcher {
|
||||
+ if len(files) == 0 {
|
||||
+ return nil
|
||||
+ }
|
||||
+ fw := &FileWatcher{
|
||||
+ done: make(chan struct{}),
|
||||
+ }
|
||||
+ go func() {
|
||||
+ modTimes := make(map[string]time.Time)
|
||||
+ for _, f := range files {
|
||||
+ stat, err := os.Stat(f)
|
||||
+ if err == nil {
|
||||
+ modTimes[f] = stat.ModTime()
|
||||
+ }
|
||||
+ }
|
||||
+ ticker := time.NewTicker(interval)
|
||||
+ defer ticker.Stop()
|
||||
+
|
||||
+ for {
|
||||
+ select {
|
||||
+ case <-fw.done:
|
||||
+ return
|
||||
+ case <-ticker.C:
|
||||
+ var changedFiles []string
|
||||
+ for _, f := range files {
|
||||
+ stat, err := os.Stat(f)
|
||||
+ if err != nil {
|
||||
+ if os.IsNotExist(err) {
|
||||
+ // File is missing or deleted.
|
||||
+ if mt, ok := modTimes[f]; ok && !mt.IsZero() {
|
||||
+ modTimes[f] = time.Time{} // mark as missing
|
||||
+ changedFiles = append(changedFiles, f)
|
||||
+ }
|
||||
+ }
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ if mt, ok := modTimes[f]; !ok || mt != stat.ModTime() {
|
||||
+ modTimes[f] = stat.ModTime()
|
||||
+ changedFiles = append(changedFiles, f)
|
||||
+ }
|
||||
+ }
|
||||
+ if len(changedFiles) > 0 {
|
||||
+ onChange(changedFiles)
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }()
|
||||
+ return fw
|
||||
+}
|
||||
+
|
||||
+// Close stops the FileWatcher.
|
||||
+func (fw *FileWatcher) Close() error {
|
||||
+ if fw != nil {
|
||||
+ close(fw.done)
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
--- a/plugin/data_provider/domain_set/domain_set.go
|
||||
+++ b/plugin/data_provider/domain_set/domain_set.go
|
||||
@@ -22,10 +22,15 @@ package domain_set
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
+ "os"
|
||||
+ "sync/atomic"
|
||||
+ "time"
|
||||
+
|
||||
"github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
||||
- "os"
|
||||
+ "go.uber.org/zap"
|
||||
)
|
||||
|
||||
const PluginType = "domain_set"
|
||||
@@ -51,33 +56,69 @@ type Args struct {
|
||||
var _ data_provider.DomainMatcherProvider = (*DomainSet)(nil)
|
||||
|
||||
type DomainSet struct {
|
||||
- mg []domain.Matcher[struct{}]
|
||||
+ mg atomic.Pointer[MatcherGroup]
|
||||
+ fw *utils.FileWatcher
|
||||
}
|
||||
|
||||
func (d *DomainSet) GetDomainMatcher() domain.Matcher[struct{}] {
|
||||
- return MatcherGroup(d.mg)
|
||||
+ return d
|
||||
+}
|
||||
+
|
||||
+func (d *DomainSet) Match(s string) (struct{}, bool) {
|
||||
+ if mg := d.mg.Load(); mg != nil {
|
||||
+ return mg.Match(s)
|
||||
+ }
|
||||
+ return struct{}{}, false
|
||||
+}
|
||||
+
|
||||
+func (d *DomainSet) Close() error {
|
||||
+ if d.fw != nil {
|
||||
+ return d.fw.Close()
|
||||
+ }
|
||||
+ return nil
|
||||
}
|
||||
|
||||
// NewDomainSet inits a DomainSet from given args.
|
||||
func NewDomainSet(bp *coremain.BP, args *Args) (*DomainSet, error) {
|
||||
ds := &DomainSet{}
|
||||
|
||||
- m := domain.NewDomainMixMatcher()
|
||||
- if err := LoadExpsAndFiles(args.Exps, args.Files, m); err != nil {
|
||||
- return nil, err
|
||||
+ loadInner := func() (*MatcherGroup, error) {
|
||||
+ var mg MatcherGroup
|
||||
+ m := domain.NewDomainMixMatcher()
|
||||
+ if err := LoadExpsAndFiles(args.Exps, args.Files, m); err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ if m.Len() > 0 {
|
||||
+ mg = append(mg, m)
|
||||
+ }
|
||||
+
|
||||
+ for _, tag := range args.Sets {
|
||||
+ provider, _ := bp.M().GetPlugin(tag).(data_provider.DomainMatcherProvider)
|
||||
+ if provider == nil {
|
||||
+ return nil, fmt.Errorf("%s is not a DomainMatcherProvider", tag)
|
||||
+ }
|
||||
+ m := provider.GetDomainMatcher()
|
||||
+ mg = append(mg, m)
|
||||
+ }
|
||||
+ return &mg, nil
|
||||
}
|
||||
- if m.Len() > 0 {
|
||||
- ds.mg = append(ds.mg, m)
|
||||
+
|
||||
+ mg, err := loadInner()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
}
|
||||
+ ds.mg.Store(mg)
|
||||
|
||||
- for _, tag := range args.Sets {
|
||||
- provider, _ := bp.M().GetPlugin(tag).(data_provider.DomainMatcherProvider)
|
||||
- if provider == nil {
|
||||
- return nil, fmt.Errorf("%s is not a DomainMatcherProvider", tag)
|
||||
- }
|
||||
- m := provider.GetDomainMatcher()
|
||||
- ds.mg = append(ds.mg, m)
|
||||
+ if len(args.Files) > 0 {
|
||||
+ ds.fw = utils.StartFileWatcher(args.Files, time.Second*3, func(changedFiles []string) {
|
||||
+ newMg, err := loadInner()
|
||||
+ if err == nil {
|
||||
+ ds.mg.Store(newMg)
|
||||
+ bp.L().Info("reloaded files", zap.Strings("files", changedFiles))
|
||||
+ }
|
||||
+ })
|
||||
}
|
||||
+
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
--- a/plugin/data_provider/ip_set/ip_set.go
|
||||
+++ b/plugin/data_provider/ip_set/ip_set.go
|
||||
@@ -22,12 +22,17 @@ package ip_set
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
- "github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
- "github.com/IrineSistiana/mosdns/v5/pkg/matcher/netlist"
|
||||
- "github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
||||
"net/netip"
|
||||
"os"
|
||||
"strings"
|
||||
+ "sync/atomic"
|
||||
+ "time"
|
||||
+
|
||||
+ "github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/matcher/netlist"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
||||
+ "go.uber.org/zap"
|
||||
)
|
||||
|
||||
const PluginType = "ip_set"
|
||||
@@ -49,31 +54,67 @@ type Args struct {
|
||||
var _ data_provider.IPMatcherProvider = (*IPSet)(nil)
|
||||
|
||||
type IPSet struct {
|
||||
- mg []netlist.Matcher
|
||||
+ mg atomic.Pointer[MatcherGroup]
|
||||
+ fw *utils.FileWatcher
|
||||
}
|
||||
|
||||
func (d *IPSet) GetIPMatcher() netlist.Matcher {
|
||||
- return MatcherGroup(d.mg)
|
||||
+ return d
|
||||
+}
|
||||
+
|
||||
+func (d *IPSet) Match(addr netip.Addr) bool {
|
||||
+ if mg := d.mg.Load(); mg != nil {
|
||||
+ return mg.Match(addr)
|
||||
+ }
|
||||
+ return false
|
||||
+}
|
||||
+
|
||||
+func (d *IPSet) Close() error {
|
||||
+ if d.fw != nil {
|
||||
+ return d.fw.Close()
|
||||
+ }
|
||||
+ return nil
|
||||
}
|
||||
|
||||
func NewIPSet(bp *coremain.BP, args *Args) (*IPSet, error) {
|
||||
p := &IPSet{}
|
||||
|
||||
- l := netlist.NewList()
|
||||
- if err := LoadFromIPsAndFiles(args.IPs, args.Files, l); err != nil {
|
||||
- return nil, err
|
||||
+ loadInner := func() (*MatcherGroup, error) {
|
||||
+ var mg MatcherGroup
|
||||
+ l := netlist.NewList()
|
||||
+ if err := LoadFromIPsAndFiles(args.IPs, args.Files, l); err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ l.Sort()
|
||||
+ if l.Len() > 0 {
|
||||
+ mg = append(mg, l)
|
||||
+ }
|
||||
+ for _, tag := range args.Sets {
|
||||
+ provider, _ := bp.M().GetPlugin(tag).(data_provider.IPMatcherProvider)
|
||||
+ if provider == nil {
|
||||
+ return nil, fmt.Errorf("%s is not an IPMatcherProvider", tag)
|
||||
+ }
|
||||
+ mg = append(mg, provider.GetIPMatcher())
|
||||
+ }
|
||||
+ return &mg, nil
|
||||
}
|
||||
- l.Sort()
|
||||
- if l.Len() > 0 {
|
||||
- p.mg = append(p.mg, l)
|
||||
+
|
||||
+ mg, err := loadInner()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
}
|
||||
- for _, tag := range args.Sets {
|
||||
- provider, _ := bp.M().GetPlugin(tag).(data_provider.IPMatcherProvider)
|
||||
- if provider == nil {
|
||||
- return nil, fmt.Errorf("%s is not an IPMatcherProvider", tag)
|
||||
- }
|
||||
- p.mg = append(p.mg, provider.GetIPMatcher())
|
||||
+ p.mg.Store(mg)
|
||||
+
|
||||
+ if len(args.Files) > 0 {
|
||||
+ p.fw = utils.StartFileWatcher(args.Files, time.Second*3, func(changedFiles []string) {
|
||||
+ newMg, err := loadInner()
|
||||
+ if err == nil {
|
||||
+ p.mg.Store(newMg)
|
||||
+ bp.L().Info("reloaded files", zap.Strings("files", changedFiles))
|
||||
+ }
|
||||
+ })
|
||||
}
|
||||
+
|
||||
return p, nil
|
||||
}
|
||||
|
||||
--- a/plugin/executable/arbitrary/arbitrary.go
|
||||
+++ b/plugin/executable/arbitrary/arbitrary.go
|
||||
@@ -23,12 +23,17 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
+ "os"
|
||||
+ "strings"
|
||||
+ "sync/atomic"
|
||||
+ "time"
|
||||
+
|
||||
"github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/zone_file"
|
||||
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
|
||||
- "os"
|
||||
- "strings"
|
||||
+ "go.uber.org/zap"
|
||||
)
|
||||
|
||||
const PluginType = "arbitrary"
|
||||
@@ -45,38 +50,68 @@ type Args struct {
|
||||
var _ sequence.Executable = (*Arbitrary)(nil)
|
||||
|
||||
type Arbitrary struct {
|
||||
- m *zone_file.Matcher
|
||||
+ m atomic.Pointer[zone_file.Matcher]
|
||||
+ fw *utils.FileWatcher
|
||||
}
|
||||
|
||||
-func NewArbitrary(args *Args) (*Arbitrary, error) {
|
||||
- m := new(zone_file.Matcher)
|
||||
- for i, s := range args.Rules {
|
||||
- if err := m.Load(strings.NewReader(s)); err != nil {
|
||||
- return nil, fmt.Errorf("failed to load rr #%d [%s], %w", i, s, err)
|
||||
- }
|
||||
- }
|
||||
- for i, file := range args.Files {
|
||||
- b, err := os.ReadFile(file)
|
||||
- if err != nil {
|
||||
- return nil, fmt.Errorf("failed to read file #%d [%s], %w", i, file, err)
|
||||
+func NewArbitrary(bp *coremain.BP, args *Args) (*Arbitrary, error) {
|
||||
+ a := &Arbitrary{}
|
||||
+
|
||||
+ loadInner := func() (*zone_file.Matcher, error) {
|
||||
+ m := new(zone_file.Matcher)
|
||||
+ for i, s := range args.Rules {
|
||||
+ if err := m.Load(strings.NewReader(s)); err != nil {
|
||||
+ return nil, fmt.Errorf("failed to load rr #%d [%s], %w", i, s, err)
|
||||
+ }
|
||||
}
|
||||
- if err := m.Load(bytes.NewReader(b)); err != nil {
|
||||
- return nil, fmt.Errorf("failed to load rr file #%d [%s], %w", i, file, err)
|
||||
+ for i, file := range args.Files {
|
||||
+ b, err := os.ReadFile(file)
|
||||
+ if err != nil {
|
||||
+ return nil, fmt.Errorf("failed to read file #%d [%s], %w", i, file, err)
|
||||
+ }
|
||||
+ if err := m.Load(bytes.NewReader(b)); err != nil {
|
||||
+ return nil, fmt.Errorf("failed to load rr file #%d [%s], %w", i, file, err)
|
||||
+ }
|
||||
}
|
||||
+ return m, nil
|
||||
+ }
|
||||
+
|
||||
+ inner, err := loadInner()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ a.m.Store(inner)
|
||||
+
|
||||
+ if len(args.Files) > 0 {
|
||||
+ a.fw = utils.StartFileWatcher(args.Files, time.Second*3, func(changedFiles []string) {
|
||||
+ newInner, err := loadInner()
|
||||
+ if err == nil {
|
||||
+ a.m.Store(newInner)
|
||||
+ bp.L().Info("reloaded files", zap.Strings("files", changedFiles))
|
||||
+ }
|
||||
+ })
|
||||
}
|
||||
- return &Arbitrary{
|
||||
- m: m,
|
||||
- }, nil
|
||||
+
|
||||
+ return a, nil
|
||||
}
|
||||
|
||||
func (a *Arbitrary) Exec(_ context.Context, qCtx *query_context.Context) error {
|
||||
- if r := a.m.Reply(qCtx.Q()); r != nil {
|
||||
- qCtx.SetResponse(r)
|
||||
+ if inner := a.m.Load(); inner != nil {
|
||||
+ if r := inner.Reply(qCtx.Q()); r != nil {
|
||||
+ qCtx.SetResponse(r)
|
||||
+ }
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (a *Arbitrary) Close() error {
|
||||
+ if a.fw != nil {
|
||||
+ return a.fw.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
-func Init(_ *coremain.BP, v any) (any, error) {
|
||||
+func Init(bp *coremain.BP, v any) (any, error) {
|
||||
args := v.(*Args)
|
||||
- return NewArbitrary(args)
|
||||
+ return NewArbitrary(bp, args)
|
||||
}
|
||||
--- a/plugin/executable/hosts/hosts.go
|
||||
+++ b/plugin/executable/hosts/hosts.go
|
||||
@@ -23,13 +23,18 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
+ "os"
|
||||
+ "sync/atomic"
|
||||
+ "time"
|
||||
+
|
||||
"github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/hosts"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
|
||||
"github.com/miekg/dns"
|
||||
- "os"
|
||||
+ "go.uber.org/zap"
|
||||
)
|
||||
|
||||
const PluginType = "hosts"
|
||||
@@ -46,44 +51,76 @@ type Args struct {
|
||||
}
|
||||
|
||||
type Hosts struct {
|
||||
- h *hosts.Hosts
|
||||
+ h atomic.Pointer[hosts.Hosts]
|
||||
+ fw *utils.FileWatcher
|
||||
}
|
||||
|
||||
-func Init(_ *coremain.BP, args any) (any, error) {
|
||||
- return NewHosts(args.(*Args))
|
||||
+func Init(bp *coremain.BP, args any) (any, error) {
|
||||
+ return NewHosts(bp, args.(*Args))
|
||||
}
|
||||
|
||||
-func NewHosts(args *Args) (*Hosts, error) {
|
||||
- m := domain.NewMixMatcher[*hosts.IPs]()
|
||||
- m.SetDefaultMatcher(domain.MatcherFull)
|
||||
- for i, entry := range args.Entries {
|
||||
- if err := domain.Load[*hosts.IPs](m, entry, hosts.ParseIPs); err != nil {
|
||||
- return nil, fmt.Errorf("failed to load entry #%d %s, %w", i, entry, err)
|
||||
- }
|
||||
- }
|
||||
- for i, file := range args.Files {
|
||||
- b, err := os.ReadFile(file)
|
||||
- if err != nil {
|
||||
- return nil, fmt.Errorf("failed to read file #%d %s, %w", i, file, err)
|
||||
+func NewHosts(bp *coremain.BP, args *Args) (*Hosts, error) {
|
||||
+ h := &Hosts{}
|
||||
+
|
||||
+ loadInner := func() (*hosts.Hosts, error) {
|
||||
+ m := domain.NewMixMatcher[*hosts.IPs]()
|
||||
+ m.SetDefaultMatcher(domain.MatcherFull)
|
||||
+ for i, entry := range args.Entries {
|
||||
+ if err := domain.Load[*hosts.IPs](m, entry, hosts.ParseIPs); err != nil {
|
||||
+ return nil, fmt.Errorf("failed to load entry #%d %s, %w", i, entry, err)
|
||||
+ }
|
||||
}
|
||||
- if err := domain.LoadFromTextReader[*hosts.IPs](m, bytes.NewReader(b), hosts.ParseIPs); err != nil {
|
||||
- return nil, fmt.Errorf("failed to load file #%d %s, %w", i, file, err)
|
||||
+ for i, file := range args.Files {
|
||||
+ b, err := os.ReadFile(file)
|
||||
+ if err != nil {
|
||||
+ return nil, fmt.Errorf("failed to read file #%d %s, %w", i, file, err)
|
||||
+ }
|
||||
+ if err := domain.LoadFromTextReader[*hosts.IPs](m, bytes.NewReader(b), hosts.ParseIPs); err != nil {
|
||||
+ return nil, fmt.Errorf("failed to load file #%d %s, %w", i, file, err)
|
||||
+ }
|
||||
}
|
||||
+ return hosts.NewHosts(m), nil
|
||||
+ }
|
||||
+
|
||||
+ inner, err := loadInner()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
}
|
||||
+ h.h.Store(inner)
|
||||
|
||||
- return &Hosts{
|
||||
- h: hosts.NewHosts(m),
|
||||
- }, nil
|
||||
+ if len(args.Files) > 0 {
|
||||
+ h.fw = utils.StartFileWatcher(args.Files, time.Second*3, func(changedFiles []string) {
|
||||
+ newInner, err := loadInner()
|
||||
+ if err == nil {
|
||||
+ h.h.Store(newInner)
|
||||
+ bp.L().Info("reloaded files", zap.Strings("files", changedFiles))
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ return h, nil
|
||||
}
|
||||
|
||||
func (h *Hosts) Response(q *dns.Msg) *dns.Msg {
|
||||
- return h.h.LookupMsg(q)
|
||||
+ if inner := h.h.Load(); inner != nil {
|
||||
+ return inner.LookupMsg(q)
|
||||
+ }
|
||||
+ return nil
|
||||
}
|
||||
|
||||
func (h *Hosts) Exec(_ context.Context, qCtx *query_context.Context) error {
|
||||
- r := h.h.LookupMsg(qCtx.Q())
|
||||
- if r != nil {
|
||||
- qCtx.SetResponse(r)
|
||||
+ if inner := h.h.Load(); inner != nil {
|
||||
+ r := inner.LookupMsg(qCtx.Q())
|
||||
+ if r != nil {
|
||||
+ qCtx.SetResponse(r)
|
||||
+ }
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (h *Hosts) Close() error {
|
||||
+ if h.fw != nil {
|
||||
+ return h.fw.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
--- a/plugin/executable/redirect/redirect.go
|
||||
+++ b/plugin/executable/redirect/redirect.go
|
||||
@@ -25,10 +25,13 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
+ "sync/atomic"
|
||||
+ "time"
|
||||
|
||||
"github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
|
||||
"github.com/miekg/dns"
|
||||
"go.uber.org/zap"
|
||||
@@ -48,11 +51,12 @@ type Args struct {
|
||||
}
|
||||
|
||||
type Redirect struct {
|
||||
- m *domain.MixMatcher[string]
|
||||
+ m atomic.Pointer[domain.MixMatcher[string]]
|
||||
+ fw *utils.FileWatcher
|
||||
}
|
||||
|
||||
func Init(bp *coremain.BP, args any) (any, error) {
|
||||
- r, err := NewRedirect(args.(*Args))
|
||||
+ r, err := NewRedirect(bp, args.(*Args))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -60,7 +64,8 @@ func Init(bp *coremain.BP, args any) (an
|
||||
return r, nil
|
||||
}
|
||||
|
||||
-func NewRedirect(args *Args) (*Redirect, error) {
|
||||
+func NewRedirect(bp *coremain.BP, args *Args) (*Redirect, error) {
|
||||
+ r := &Redirect{}
|
||||
parseFunc := func(s string) (p, v string, err error) {
|
||||
f := strings.Fields(s)
|
||||
if len(f) != 2 {
|
||||
@@ -68,23 +73,44 @@ func NewRedirect(args *Args) (*Redirect,
|
||||
}
|
||||
return f[0], dns.Fqdn(f[1]), nil
|
||||
}
|
||||
- m := domain.NewMixMatcher[string]()
|
||||
- m.SetDefaultMatcher(domain.MatcherFull)
|
||||
- for i, rule := range args.Rules {
|
||||
- if err := domain.Load[string](m, rule, parseFunc); err != nil {
|
||||
- return nil, fmt.Errorf("failed to load rule #%d %s, %w", i, rule, err)
|
||||
- }
|
||||
- }
|
||||
- for i, file := range args.Files {
|
||||
- b, err := os.ReadFile(file)
|
||||
- if err != nil {
|
||||
- return nil, fmt.Errorf("failed to read file #%d %s, %w", i, file, err)
|
||||
+
|
||||
+ loadInner := func() (*domain.MixMatcher[string], error) {
|
||||
+ m := domain.NewMixMatcher[string]()
|
||||
+ m.SetDefaultMatcher(domain.MatcherFull)
|
||||
+ for i, rule := range args.Rules {
|
||||
+ if err := domain.Load[string](m, rule, parseFunc); err != nil {
|
||||
+ return nil, fmt.Errorf("failed to load rule #%d %s, %w", i, rule, err)
|
||||
+ }
|
||||
}
|
||||
- if err := domain.LoadFromTextReader[string](m, bytes.NewReader(b), parseFunc); err != nil {
|
||||
- return nil, fmt.Errorf("failed to load file #%d %s, %w", i, file, err)
|
||||
+ for i, file := range args.Files {
|
||||
+ b, err := os.ReadFile(file)
|
||||
+ if err != nil {
|
||||
+ return nil, fmt.Errorf("failed to read file #%d %s, %w", i, file, err)
|
||||
+ }
|
||||
+ if err := domain.LoadFromTextReader[string](m, bytes.NewReader(b), parseFunc); err != nil {
|
||||
+ return nil, fmt.Errorf("failed to load file #%d %s, %w", i, file, err)
|
||||
+ }
|
||||
}
|
||||
+ return m, nil
|
||||
+ }
|
||||
+
|
||||
+ inner, err := loadInner()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ r.m.Store(inner)
|
||||
+
|
||||
+ if len(args.Files) > 0 {
|
||||
+ r.fw = utils.StartFileWatcher(args.Files, time.Second*3, func(changedFiles []string) {
|
||||
+ newInner, err := loadInner()
|
||||
+ if err == nil {
|
||||
+ r.m.Store(newInner)
|
||||
+ bp.L().Info("reloaded files", zap.Strings("files", changedFiles), zap.Int("length", newInner.Len()))
|
||||
+ }
|
||||
+ })
|
||||
}
|
||||
- return &Redirect{m: m}, nil
|
||||
+
|
||||
+ return r, nil
|
||||
}
|
||||
|
||||
func (r *Redirect) Exec(ctx context.Context, qCtx *query_context.Context, next sequence.ChainWalker) error {
|
||||
@@ -94,7 +120,12 @@ func (r *Redirect) Exec(ctx context.Cont
|
||||
}
|
||||
|
||||
orgQName := q.Question[0].Name
|
||||
- redirectTarget, ok := r.m.Match(orgQName)
|
||||
+ inner := r.m.Load()
|
||||
+ if inner == nil {
|
||||
+ return next.ExecNext(ctx, qCtx)
|
||||
+ }
|
||||
+
|
||||
+ redirectTarget, ok := inner.Match(orgQName)
|
||||
if !ok {
|
||||
return next.ExecNext(ctx, qCtx)
|
||||
}
|
||||
@@ -104,16 +135,16 @@ func (r *Redirect) Exec(ctx context.Cont
|
||||
q.Question[0].Name = orgQName
|
||||
}()
|
||||
err := next.ExecNext(ctx, qCtx)
|
||||
- if r := qCtx.R(); r != nil {
|
||||
+ if rResp := qCtx.R(); rResp != nil {
|
||||
// Restore original query name.
|
||||
- for i := range r.Question {
|
||||
- if r.Question[i].Name == redirectTarget {
|
||||
- r.Question[i].Name = orgQName
|
||||
+ for i := range rResp.Question {
|
||||
+ if rResp.Question[i].Name == redirectTarget {
|
||||
+ rResp.Question[i].Name = orgQName
|
||||
}
|
||||
}
|
||||
|
||||
// Insert a CNAME record.
|
||||
- newAns := make([]dns.RR, 1, len(r.Answer)+1)
|
||||
+ newAns := make([]dns.RR, 1, len(rResp.Answer)+1)
|
||||
newAns[0] = &dns.CNAME{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: orgQName,
|
||||
@@ -123,12 +154,22 @@ func (r *Redirect) Exec(ctx context.Cont
|
||||
},
|
||||
Target: redirectTarget,
|
||||
}
|
||||
- newAns = append(newAns, r.Answer...)
|
||||
- r.Answer = newAns
|
||||
+ newAns = append(newAns, rResp.Answer...)
|
||||
+ rResp.Answer = newAns
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Redirect) Len() int {
|
||||
- return r.m.Len()
|
||||
+ if inner := r.m.Load(); inner != nil {
|
||||
+ return inner.Len()
|
||||
+ }
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+func (r *Redirect) Close() error {
|
||||
+ if r.fw != nil {
|
||||
+ return r.fw.Close()
|
||||
+ }
|
||||
+ return nil
|
||||
}
|
||||
@@ -1,427 +0,0 @@
|
||||
From 64614017e674960638bac87b4a2f9c0aea0065e6 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Fri, 1 May 2026 01:35:59 +0800
|
||||
Subject: [PATCH] add adblock_set database plugin
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
.../data_provider/adblock_set/adblock_set.go | 122 ++++++++++++++++++
|
||||
.../adblock_set/adblock_set_test.go | 107 +++++++++++++++
|
||||
plugin/data_provider/adblock_set/matcher.go | 43 ++++++
|
||||
plugin/data_provider/adblock_set/parser.go | 115 +++++++++++++++++
|
||||
plugin/enabled_plugins.go | 1 +
|
||||
5 files changed, 388 insertions(+)
|
||||
create mode 100644 plugin/data_provider/adblock_set/adblock_set.go
|
||||
create mode 100644 plugin/data_provider/adblock_set/adblock_set_test.go
|
||||
create mode 100644 plugin/data_provider/adblock_set/matcher.go
|
||||
create mode 100644 plugin/data_provider/adblock_set/parser.go
|
||||
|
||||
--- /dev/null
|
||||
+++ b/plugin/data_provider/adblock_set/adblock_set.go
|
||||
@@ -0,0 +1,122 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025, IrineSistiana
|
||||
+ *
|
||||
+ * This file is part of mosdns.
|
||||
+ *
|
||||
+ * mosdns is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * mosdns is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+package adblock_set
|
||||
+
|
||||
+import (
|
||||
+ "fmt"
|
||||
+ "os"
|
||||
+ "sync/atomic"
|
||||
+ "time"
|
||||
+
|
||||
+ "github.com/IrineSistiana/mosdns/v5/coremain"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/utils"
|
||||
+ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
|
||||
+ "go.uber.org/zap"
|
||||
+)
|
||||
+
|
||||
+const PluginType = "adblock_set"
|
||||
+
|
||||
+func init() {
|
||||
+ coremain.RegNewPluginFunc(PluginType, Init, func() any { return new(Args) })
|
||||
+}
|
||||
+
|
||||
+func Init(bp *coremain.BP, args any) (any, error) {
|
||||
+ m, err := NewAdblockSet(bp, args.(*Args))
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ return m, nil
|
||||
+}
|
||||
+
|
||||
+type Args struct {
|
||||
+ Files []string `yaml:"files"`
|
||||
+}
|
||||
+
|
||||
+var _ data_provider.DomainMatcherProvider = (*AdblockSet)(nil)
|
||||
+
|
||||
+type AdblockSet struct {
|
||||
+ matcher atomic.Pointer[AdblockMatcher]
|
||||
+ fw *utils.FileWatcher
|
||||
+}
|
||||
+
|
||||
+func (d *AdblockSet) GetDomainMatcher() domain.Matcher[struct{}] {
|
||||
+ return d
|
||||
+}
|
||||
+
|
||||
+func (d *AdblockSet) Match(s string) (struct{}, bool) {
|
||||
+ if m := d.matcher.Load(); m != nil {
|
||||
+ return m.Match(s)
|
||||
+ }
|
||||
+ return struct{}{}, false
|
||||
+}
|
||||
+
|
||||
+func (d *AdblockSet) Close() error {
|
||||
+ if d.fw != nil {
|
||||
+ return d.fw.Close()
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func NewAdblockSet(bp *coremain.BP, args *Args) (*AdblockSet, error) {
|
||||
+ ds := &AdblockSet{}
|
||||
+
|
||||
+ loadInner := func() (*AdblockMatcher, error) {
|
||||
+ m := &AdblockMatcher{
|
||||
+ blacklist: domain.NewMixMatcher[struct{}](),
|
||||
+ whitelist: domain.NewMixMatcher[struct{}](),
|
||||
+ }
|
||||
+ for _, f := range args.Files {
|
||||
+ if len(f) == 0 {
|
||||
+ continue
|
||||
+ }
|
||||
+ file, err := os.Open(f)
|
||||
+ if err != nil {
|
||||
+ return nil, fmt.Errorf("failed to open file %s: %w", f, err)
|
||||
+ }
|
||||
+ if err := ParseRules(file, m.blacklist, m.whitelist); err != nil {
|
||||
+ file.Close()
|
||||
+ return nil, fmt.Errorf("failed to parse rules from %s: %w", f, err)
|
||||
+ }
|
||||
+ file.Close()
|
||||
+ }
|
||||
+ return m, nil
|
||||
+ }
|
||||
+
|
||||
+ m, err := loadInner()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ ds.matcher.Store(m)
|
||||
+
|
||||
+ if len(args.Files) > 0 {
|
||||
+ ds.fw = utils.StartFileWatcher(args.Files, time.Second*3, func(changedFiles []string) {
|
||||
+ newM, err := loadInner()
|
||||
+ if err == nil {
|
||||
+ ds.matcher.Store(newM)
|
||||
+ bp.L().Info("reloaded adblock files", zap.Strings("files", changedFiles))
|
||||
+ } else {
|
||||
+ bp.L().Error("failed to reload adblock files", zap.Error(err))
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ return ds, nil
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/plugin/data_provider/adblock_set/adblock_set_test.go
|
||||
@@ -0,0 +1,107 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025, IrineSistiana
|
||||
+ *
|
||||
+ * This file is part of mosdns.
|
||||
+ *
|
||||
+ * mosdns is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * mosdns is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+package adblock_set
|
||||
+
|
||||
+import (
|
||||
+ "strings"
|
||||
+ "testing"
|
||||
+
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
+ "github.com/stretchr/testify/assert"
|
||||
+)
|
||||
+
|
||||
+func TestParseAndMatch(t *testing.T) {
|
||||
+ rules := `
|
||||
+! Comment
|
||||
+# Another comment
|
||||
+||example.com^
|
||||
+@@||whitelist.com^
|
||||
+|exact.com|
|
||||
+@@|white-exact.com|
|
||||
+/.*regex.*/
|
||||
+@@/.*white-regex.*/
|
||||
+*keyword*
|
||||
+@@*white-keyword*
|
||||
+blocked.com
|
||||
+domain:ntp.org
|
||||
+full:metrics.icloud.com
|
||||
+`
|
||||
+ blacklist := domain.NewMixMatcher[struct{}]()
|
||||
+ whitelist := domain.NewMixMatcher[struct{}]()
|
||||
+
|
||||
+ err := ParseRules(strings.NewReader(rules), blacklist, whitelist)
|
||||
+ assert.NoError(t, err)
|
||||
+
|
||||
+ matcher := &AdblockMatcher{
|
||||
+ blacklist: blacklist,
|
||||
+ whitelist: whitelist,
|
||||
+ }
|
||||
+
|
||||
+ tests := []struct {
|
||||
+ domain string
|
||||
+ want bool
|
||||
+ }{
|
||||
+ {"example.com", true},
|
||||
+ {"sub.example.com", true},
|
||||
+ {"whitelist.com", false},
|
||||
+ {"sub.whitelist.com", false},
|
||||
+ {"exact.com", true},
|
||||
+ {"sub.exact.com", false}, // |exact.com| is exact match
|
||||
+ {"white-exact.com", false},
|
||||
+ {"myregex123", true},
|
||||
+ {"mywhite-regex123", false},
|
||||
+ {"somekeywordhere", true},
|
||||
+ {"some-white-keyword-here", false},
|
||||
+ {"blocked.com", true},
|
||||
+ {"other.com", false},
|
||||
+ {"ntp.org", true}, // matched by domain:ntp.org
|
||||
+ {"sub.ntp.org", true}, // matched by domain:ntp.org
|
||||
+ {"metrics.icloud.com", true}, // matched by full:metrics.icloud.com
|
||||
+ {"sub.metrics.icloud.com", false}, // full match only
|
||||
+ }
|
||||
+
|
||||
+ for _, tt := range tests {
|
||||
+ _, ok := matcher.Match(tt.domain)
|
||||
+ assert.Equal(t, tt.want, ok, "Match(%s)", tt.domain)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func TestStripOptions(t *testing.T) {
|
||||
+ rules := `
|
||||
+||example.com^$important,third-party
|
||||
+@@||whitelist.com^$dnstype=A
|
||||
+`
|
||||
+ blacklist := domain.NewMixMatcher[struct{}]()
|
||||
+ whitelist := domain.NewMixMatcher[struct{}]()
|
||||
+
|
||||
+ err := ParseRules(strings.NewReader(rules), blacklist, whitelist)
|
||||
+ assert.NoError(t, err)
|
||||
+
|
||||
+ matcher := &AdblockMatcher{
|
||||
+ blacklist: blacklist,
|
||||
+ whitelist: whitelist,
|
||||
+ }
|
||||
+
|
||||
+ _, ok := matcher.Match("example.com")
|
||||
+ assert.True(t, ok)
|
||||
+
|
||||
+ _, ok = matcher.Match("whitelist.com")
|
||||
+ assert.False(t, ok)
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/plugin/data_provider/adblock_set/matcher.go
|
||||
@@ -0,0 +1,43 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025, IrineSistiana
|
||||
+ *
|
||||
+ * This file is part of mosdns.
|
||||
+ *
|
||||
+ * mosdns is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * mosdns is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+package adblock_set
|
||||
+
|
||||
+import (
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
+)
|
||||
+
|
||||
+type AdblockMatcher struct {
|
||||
+ blacklist *domain.MixMatcher[struct{}]
|
||||
+ whitelist *domain.MixMatcher[struct{}]
|
||||
+}
|
||||
+
|
||||
+func (m *AdblockMatcher) Match(s string) (struct{}, bool) {
|
||||
+ // 1. Check whitelist. If matched, it's NOT a hit for the adblock set.
|
||||
+ if _, ok := m.whitelist.Match(s); ok {
|
||||
+ return struct{}{}, false
|
||||
+ }
|
||||
+
|
||||
+ // 2. Check blacklist.
|
||||
+ if _, ok := m.blacklist.Match(s); ok {
|
||||
+ return struct{}{}, true
|
||||
+ }
|
||||
+
|
||||
+ return struct{}{}, false
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/plugin/data_provider/adblock_set/parser.go
|
||||
@@ -0,0 +1,115 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2025, IrineSistiana
|
||||
+ *
|
||||
+ * This file is part of mosdns.
|
||||
+ *
|
||||
+ * mosdns is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * mosdns is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+package adblock_set
|
||||
+
|
||||
+import (
|
||||
+ "bufio"
|
||||
+ "io"
|
||||
+ "strings"
|
||||
+
|
||||
+ "github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
+)
|
||||
+
|
||||
+// ParseRules reads AdBlock rules from r and adds them to blacklist and whitelist matchers.
|
||||
+func ParseRules(r io.Reader, blacklist, whitelist *domain.MixMatcher[struct{}]) error {
|
||||
+ scanner := bufio.NewScanner(r)
|
||||
+ for scanner.Scan() {
|
||||
+ line := strings.TrimSpace(scanner.Text())
|
||||
+ if line == "" || line[0] == '!' || line[0] == '#' {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ // Handle whitelists
|
||||
+ isWhitelist := false
|
||||
+ if strings.HasPrefix(line, "@@") {
|
||||
+ isWhitelist = true
|
||||
+ line = line[2:]
|
||||
+ }
|
||||
+
|
||||
+ // Handle comments in rules (e.g., rule # comment)
|
||||
+ // But in AdBlock, # is usually for element hiding (##) or CSS selectors.
|
||||
+ // For DNS rules, we ignore anything starting with #.
|
||||
+ if strings.Contains(line, "##") || strings.Contains(line, "#?#") || strings.Contains(line, "#$#") {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ // Strip options (e.g., $important, $third-party)
|
||||
+ if idx := strings.LastIndex(line, "$"); idx != -1 {
|
||||
+ // Check if it's a regex or something else.
|
||||
+ // In ABP, $ marks the start of options.
|
||||
+ line = line[:idx]
|
||||
+ }
|
||||
+
|
||||
+ if line == "" {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ target := blacklist
|
||||
+ if isWhitelist {
|
||||
+ target = whitelist
|
||||
+ }
|
||||
+
|
||||
+ if err := parseAndAddRule(line, target); err != nil {
|
||||
+ // Skip invalid rules but maybe we should log them?
|
||||
+ continue
|
||||
+ }
|
||||
+ }
|
||||
+ return scanner.Err()
|
||||
+}
|
||||
+
|
||||
+func parseAndAddRule(rule string, m *domain.MixMatcher[struct{}]) error {
|
||||
+ // 0. Native MosDNS rules: type:pattern
|
||||
+ if strings.Contains(rule, ":") {
|
||||
+ typ, _, _ := strings.Cut(rule, ":")
|
||||
+ switch typ {
|
||||
+ case "full", "domain", "regexp", "keyword":
|
||||
+ return m.Add(rule, struct{}{})
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // 1. Regex: /regexp/
|
||||
+ if strings.HasPrefix(rule, "/") && strings.HasSuffix(rule, "/") && len(rule) > 2 {
|
||||
+ return m.Add("regexp:"+rule[1:len(rule)-1], struct{}{})
|
||||
+ }
|
||||
+
|
||||
+ // 2. Subdomain: ||example.com^
|
||||
+ if strings.HasPrefix(rule, "||") {
|
||||
+ domainStr := rule[2:]
|
||||
+ if strings.HasSuffix(domainStr, "^") {
|
||||
+ domainStr = domainStr[:len(domainStr)-1]
|
||||
+ }
|
||||
+ return m.Add("domain:"+domainStr, struct{}{})
|
||||
+ }
|
||||
+
|
||||
+ // 3. Exact match: |example.com|
|
||||
+ if strings.HasPrefix(rule, "|") && strings.HasSuffix(rule, "|") && len(rule) > 2 {
|
||||
+ return m.Add("full:"+rule[1:len(rule)-1], struct{}{})
|
||||
+ }
|
||||
+
|
||||
+ // 4. Keyword: *keyword*
|
||||
+ if strings.HasPrefix(rule, "*") && strings.HasSuffix(rule, "*") && len(rule) > 2 {
|
||||
+ return m.Add("keyword:"+rule[1:len(rule)-1], struct{}{})
|
||||
+ }
|
||||
+
|
||||
+ // 5. Default: treat as exact match if it looks like a domain
|
||||
+ // Many lists are just a list of domains.
|
||||
+ // AdGuard Home treats rules without || or ^ as exact matches.
|
||||
+ return m.Add("full:"+rule, struct{}{})
|
||||
+}
|
||||
--- a/plugin/enabled_plugins.go
|
||||
+++ b/plugin/enabled_plugins.go
|
||||
@@ -22,6 +22,7 @@ package plugin
|
||||
// data providers
|
||||
import (
|
||||
// data provider
|
||||
+ _ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider/adblock_set"
|
||||
_ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider/domain_set"
|
||||
_ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider/ip_set"
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
From 8f9c6ca1ac8e9b5e10a5c45f3f338546424c95f1 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Sat, 2 May 2026 13:43:31 +0800
|
||||
Subject: [PATCH] feat(adblock_set): support hosts file format blocking rules
|
||||
|
||||
Parse lines like "0.0.0.0 domain" and "127.0.0.1 domain" as exact-match
|
||||
blocking rules, compatible with AdGuard Home hosts-style lists.
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
plugin/data_provider/adblock_set/adblock_set_test.go | 6 ++++++
|
||||
plugin/data_provider/adblock_set/parser.go | 12 ++++++++++++
|
||||
2 files changed, 18 insertions(+)
|
||||
|
||||
--- a/plugin/data_provider/adblock_set/adblock_set_test.go
|
||||
+++ b/plugin/data_provider/adblock_set/adblock_set_test.go
|
||||
@@ -42,6 +42,8 @@ func TestParseAndMatch(t *testing.T) {
|
||||
blocked.com
|
||||
domain:ntp.org
|
||||
full:metrics.icloud.com
|
||||
+0.0.0.0 singlehotmilf.online
|
||||
+127.0.0.1 deezer.deliveryengine.adswizz.com
|
||||
`
|
||||
blacklist := domain.NewMixMatcher[struct{}]()
|
||||
whitelist := domain.NewMixMatcher[struct{}]()
|
||||
@@ -75,6 +77,10 @@ full:metrics.icloud.com
|
||||
{"sub.ntp.org", true}, // matched by domain:ntp.org
|
||||
{"metrics.icloud.com", true}, // matched by full:metrics.icloud.com
|
||||
{"sub.metrics.icloud.com", false}, // full match only
|
||||
+ {"singlehotmilf.online", true}, // hosts: 0.0.0.0
|
||||
+ {"sub.singlehotmilf.online", false}, // hosts: exact match only
|
||||
+ {"deezer.deliveryengine.adswizz.com", true}, // hosts: 127.0.0.1
|
||||
+ {"sub.deezer.deliveryengine.adswizz.com", false}, // hosts: exact match only
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
--- a/plugin/data_provider/adblock_set/parser.go
|
||||
+++ b/plugin/data_provider/adblock_set/parser.go
|
||||
@@ -22,6 +22,7 @@ package adblock_set
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
+ "net"
|
||||
"strings"
|
||||
|
||||
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
|
||||
@@ -36,6 +37,17 @@ func ParseRules(r io.Reader, blacklist,
|
||||
continue
|
||||
}
|
||||
|
||||
+ // Handle hosts file format: "0.0.0.0 domain" or "127.0.0.1 domain"
|
||||
+ if fields := strings.Fields(line); len(fields) >= 2 {
|
||||
+ if ip := net.ParseIP(fields[0]); ip != nil {
|
||||
+ host := fields[1]
|
||||
+ if host != "" && host != "localhost" {
|
||||
+ _ = blacklist.Add("full:"+host, struct{}{})
|
||||
+ }
|
||||
+ continue
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// Handle whitelists
|
||||
isWhitelist := false
|
||||
if strings.HasPrefix(line, "@@") {
|
||||
@@ -1,280 +0,0 @@
|
||||
From e2a50186add36064f78015b163d725f1fe9821d0 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Thu, 2 Jul 2026 22:37:40 +0800
|
||||
Subject: [PATCH] feat: add size and backups config for log file rotation
|
||||
|
||||
- `log.size`: limits active log file size, supports K/M/G/T (default 1M)
|
||||
- `log.backups`: limits max retained backup files (default 3)
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
mlog/logger.go | 25 +++++-
|
||||
mlog/rotator.go | 219 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 241 insertions(+), 3 deletions(-)
|
||||
create mode 100644 mlog/rotator.go
|
||||
|
||||
--- a/mlog/logger.go
|
||||
+++ b/mlog/logger.go
|
||||
@@ -38,6 +38,14 @@ type LogConfig struct {
|
||||
|
||||
// Production enables json output.
|
||||
Production bool `yaml:"production"`
|
||||
+
|
||||
+ // Size of log file limit. Default is 1M.
|
||||
+ // Supported units: K, M, G, T. If no unit, defaults to M.
|
||||
+ Size string `yaml:"size"`
|
||||
+
|
||||
+ // Max number of old log files to retain. Default is 3.
|
||||
+ // Set to a negative number to retain all files.
|
||||
+ Backups int `yaml:"backups"`
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -57,11 +65,22 @@ func NewLogger(lc LogConfig) (*zap.Logge
|
||||
|
||||
var out zapcore.WriteSyncer
|
||||
if lf := lc.File; len(lf) > 0 {
|
||||
- f, _, err := zap.Open(lf)
|
||||
+ maxSize, err := ParseSize(lc.Size)
|
||||
if err != nil {
|
||||
- return nil, fmt.Errorf("open log file: %w", err)
|
||||
+ return nil, fmt.Errorf("invalid log size limit: %w", err)
|
||||
+ }
|
||||
+
|
||||
+ backups := lc.Backups
|
||||
+ if backups == 0 {
|
||||
+ backups = 3
|
||||
+ }
|
||||
+
|
||||
+ rotator := &Rotator{
|
||||
+ Filename: lf,
|
||||
+ MaxSize: maxSize,
|
||||
+ MaxBackups: backups,
|
||||
}
|
||||
- out = zapcore.Lock(f)
|
||||
+ out = zapcore.AddSync(rotator)
|
||||
} else {
|
||||
out = stderr
|
||||
}
|
||||
--- /dev/null
|
||||
+++ b/mlog/rotator.go
|
||||
@@ -0,0 +1,219 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2020-2022, IrineSistiana
|
||||
+ *
|
||||
+ * This file is part of mosdns.
|
||||
+ *
|
||||
+ * mosdns is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * mosdns is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+ */
|
||||
+
|
||||
+package mlog
|
||||
+
|
||||
+import (
|
||||
+ "fmt"
|
||||
+ "os"
|
||||
+ "path/filepath"
|
||||
+ "sort"
|
||||
+ "strconv"
|
||||
+ "strings"
|
||||
+ "sync"
|
||||
+ "time"
|
||||
+)
|
||||
+
|
||||
+type Rotator struct {
|
||||
+ Filename string
|
||||
+ MaxSize int64
|
||||
+ MaxBackups int
|
||||
+
|
||||
+ size int64
|
||||
+ f *os.File
|
||||
+ mu sync.Mutex
|
||||
+}
|
||||
+
|
||||
+func (r *Rotator) Write(p []byte) (n int, err error) {
|
||||
+ r.mu.Lock()
|
||||
+ defer r.mu.Unlock()
|
||||
+
|
||||
+ if r.f == nil {
|
||||
+ if err := r.open(); err != nil {
|
||||
+ return 0, err
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ writeLen := int64(len(p))
|
||||
+ if r.MaxSize > 0 && r.size+writeLen > r.MaxSize {
|
||||
+ if err := r.rotate(); err != nil {
|
||||
+ return 0, err
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ n, err = r.f.Write(p)
|
||||
+ r.size += int64(n)
|
||||
+ return n, err
|
||||
+}
|
||||
+
|
||||
+func (r *Rotator) open() error {
|
||||
+ info, err := os.Stat(r.Filename)
|
||||
+ if os.IsNotExist(err) {
|
||||
+ return r.openNew()
|
||||
+ }
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ r.size = info.Size()
|
||||
+ f, err := os.OpenFile(r.Filename, os.O_APPEND|os.O_WRONLY, 0644)
|
||||
+ if err != nil {
|
||||
+ return r.openNew()
|
||||
+ }
|
||||
+ r.f = f
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (r *Rotator) openNew() error {
|
||||
+ err := os.MkdirAll(filepath.Dir(r.Filename), 0755)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ f, err := os.OpenFile(r.Filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ r.f = f
|
||||
+ r.size = 0
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (r *Rotator) rotate() error {
|
||||
+ if r.f != nil {
|
||||
+ r.f.Close()
|
||||
+ r.f = nil
|
||||
+ }
|
||||
+ _, err := os.Stat(r.Filename)
|
||||
+ if err == nil {
|
||||
+ ext := filepath.Ext(r.Filename)
|
||||
+ name := strings.TrimSuffix(r.Filename, ext)
|
||||
+ // Windows doesn't allow colons in filenames, so use dashes for time
|
||||
+ newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("2006-01-02T15-04-05.000"), ext)
|
||||
+ os.Rename(r.Filename, newName)
|
||||
+ }
|
||||
+ err = r.openNew()
|
||||
+ if err == nil {
|
||||
+ r.cleanupBackups()
|
||||
+ }
|
||||
+ return err
|
||||
+}
|
||||
+
|
||||
+func (r *Rotator) cleanupBackups() {
|
||||
+ if r.MaxBackups < 0 {
|
||||
+ return // < 0 means keep all
|
||||
+ }
|
||||
+
|
||||
+ dir := filepath.Dir(r.Filename)
|
||||
+ ext := filepath.Ext(r.Filename)
|
||||
+ name := strings.TrimSuffix(filepath.Base(r.Filename), ext)
|
||||
+
|
||||
+ entries, err := os.ReadDir(dir)
|
||||
+ if err != nil {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ var backups []string
|
||||
+ prefix := name + "-"
|
||||
+ for _, entry := range entries {
|
||||
+ if entry.IsDir() {
|
||||
+ continue
|
||||
+ }
|
||||
+ n := entry.Name()
|
||||
+ if strings.HasPrefix(n, prefix) && strings.HasSuffix(n, ext) {
|
||||
+ // Basic validation of the timestamp length
|
||||
+ timestamp := n[len(prefix) : len(n)-len(ext)]
|
||||
+ if len(timestamp) == 23 {
|
||||
+ backups = append(backups, filepath.Join(dir, n))
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if len(backups) <= r.MaxBackups {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ // Sort alphabetically, which sorts by time since format is 2006-01-02T15-04-05.000
|
||||
+ sort.Strings(backups)
|
||||
+
|
||||
+ toDelete := len(backups) - r.MaxBackups
|
||||
+ for i := 0; i < toDelete; i++ {
|
||||
+ os.Remove(backups[i])
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func (r *Rotator) Sync() error {
|
||||
+ r.mu.Lock()
|
||||
+ defer r.mu.Unlock()
|
||||
+ if r.f != nil {
|
||||
+ return r.f.Sync()
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (r *Rotator) Close() error {
|
||||
+ r.mu.Lock()
|
||||
+ defer r.mu.Unlock()
|
||||
+ if r.f != nil {
|
||||
+ err := r.f.Close()
|
||||
+ r.f = nil
|
||||
+ return err
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+// ParseSize parses the size string and returns bytes.
|
||||
+// Supports K, M, G, T units. If no unit, defaults to M.
|
||||
+func ParseSize(s string) (int64, error) {
|
||||
+ if s == "" {
|
||||
+ return 1024 * 1024, nil // Default 1M
|
||||
+ }
|
||||
+ s = strings.ToUpper(strings.TrimSpace(s))
|
||||
+
|
||||
+ var unit string
|
||||
+ var valStr string
|
||||
+ for i, c := range s {
|
||||
+ if c >= 'A' && c <= 'Z' {
|
||||
+ valStr = s[:i]
|
||||
+ unit = s[i:]
|
||||
+ break
|
||||
+ }
|
||||
+ }
|
||||
+ if unit == "" {
|
||||
+ valStr = s
|
||||
+ unit = "M" // default to M
|
||||
+ }
|
||||
+ valStr = strings.TrimSpace(valStr)
|
||||
+
|
||||
+ val, err := strconv.ParseInt(valStr, 10, 64)
|
||||
+ if err != nil {
|
||||
+ return 0, err
|
||||
+ }
|
||||
+
|
||||
+ switch unit {
|
||||
+ case "K", "KB":
|
||||
+ return val * 1024, nil
|
||||
+ case "M", "MB":
|
||||
+ return val * 1024 * 1024, nil
|
||||
+ case "G", "GB":
|
||||
+ return val * 1024 * 1024 * 1024, nil
|
||||
+ case "T", "TB":
|
||||
+ return val * 1024 * 1024 * 1024 * 1024, nil
|
||||
+ default:
|
||||
+ return 0, fmt.Errorf("invalid size unit: %s", unit)
|
||||
+ }
|
||||
+}
|
||||
@@ -5,22 +5,23 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=uugamebooster
|
||||
PKG_VERSION:=12.1.4
|
||||
PKG_VERSION:=14.0.6
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(ARCH).tar.gz
|
||||
PKG_SOURCE_URL:=https://uurouter.gdl.netease.com/uuplugin/openwrt-$(ARCH)/v$(PKG_VERSION)/uu.tar.gz?
|
||||
ifeq ($(ARCH),aarch64)
|
||||
PKG_HASH:=f140dc99af5a67367e63c811ba5b555c748dea32c3b11c6b5bde6afc25ac960c
|
||||
PKG_HASH:=4fe6fcad525c525ad530af69f102d90c1189330e4e3c3183b577ddde27731e2a
|
||||
else ifeq ($(ARCH),arm)
|
||||
PKG_HASH:=d531ff8ccb8b14abbac2d46d8cf1697114c981b059b9fb88adc19322be1ec2af
|
||||
PKG_HASH:=e8693a284d0a9445e73f8d2e9c3d330364cc6371d63c19da03f8e8c47f076caf
|
||||
else ifeq ($(ARCH),mipsel)
|
||||
PKG_HASH:=c9003945872a106fd46207afb130a6741ee832bdc3273e2257f35a092cfd966a
|
||||
PKG_HASH:=6fd2497bfdcf228de050119f7f593547a0da3eca9c50baa6bf8d5da6e366c575
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
PKG_HASH:=1dd419ac166b124f8d83e4075a65b6547ba589f976894065ce551a66313a6e84
|
||||
PKG_HASH:=1becd5ef81d257b22002f208cd303b04e421c7da4231523b7d82da2c7193b57f
|
||||
endif
|
||||
|
||||
PKG_LICENSE:=Proprietary
|
||||
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
@@ -61,4 +62,4 @@ define Package/uugamebooster/install
|
||||
$(INSTALL_BIN) $(CURDIR)/files/uugamebooster.init $(1)/etc/init.d/uugamebooster
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,uugamebooster))
|
||||
$(eval $(call BuildPackage,uugamebooster))
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
config uugamebooster 'config'
|
||||
option enabled '0'
|
||||
|
||||
Executable → Regular
+1
-1
@@ -34,4 +34,4 @@ reload_service() {
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$CONF"
|
||||
}
|
||||
}
|
||||
Executable → Regular
+2
-2
@@ -19,7 +19,7 @@ for ARCH in "aarch64" "arm" "mipsel" "x86_64"; do
|
||||
echo -e "Version mismatch. Expected version: $VERSION, got $FILE_VER."
|
||||
exit 1
|
||||
else
|
||||
curl -fsSL "http://uurouter.gdl.netease.com/uuplugin/openwrt-$ARCH/v$VERSION/uu.tar.gz" -o "$CURDIR/uu-$ARCH.tar.gz"
|
||||
curl -fsSL "http://uurouter.gdl04.netease.com/uuplugin/openwrt-$ARCH/v$VERSION/uu.tar.gz" -o "$CURDIR/uu-$ARCH.tar.gz"
|
||||
ACTUAL_MD5="$(md5sum "$CURDIR/uu-$ARCH.tar.gz" | awk '{print $1}')"
|
||||
if [ "$ACTUAL_MD5" != "$FILE_MD5" ]; then
|
||||
echo -e "HASH mismatch. Expected md5: $FILE_MD5, got $ACTUAL_MD5."
|
||||
@@ -32,4 +32,4 @@ for ARCH in "aarch64" "arm" "mipsel" "x86_64"; do
|
||||
fi
|
||||
done
|
||||
|
||||
sed -i "s,PKG_VERSION:=.*,PKG_VERSION:=$VERSION,g" "$CURDIR/Makefile"
|
||||
sed -i "s,PKG_VERSION:=.*,PKG_VERSION:=$VERSION,g" "$CURDIR/Makefile"
|
||||
+8
-9
@@ -7,14 +7,13 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=v2dat
|
||||
PKG_SOURCE_DATE:=2022-12-15
|
||||
PKG_SOURCE_VERSION:=47b8ee51fb528e11e1a83453b7e767a18d20d1f7
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=0.1.5
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/urlesistiana/v2dat/tar.gz/$(PKG_SOURCE_VERSION)?
|
||||
PKG_HASH:=dca45a31006aca3dba5f543f6990ca755ffb2bde8e533cc2bbe6bac9ec12f157
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/kenzok8/v2dat/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=149319fa274a7d0b054d848f782ad103f653321380785cd1734642e434f99176
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILE:=LICENSE
|
||||
@@ -25,7 +24,7 @@ PKG_BUILD_PARALLEL:=1
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_BUILD_FLAGS:=no-mips16
|
||||
|
||||
GO_PKG:=github.com/urlesistiana/v2dat
|
||||
GO_PKG:=github.com/kenzok8/v2dat
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||
@@ -34,7 +33,7 @@ define Package/v2dat
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=V2ray geo/ip data unpack tools
|
||||
URL:=https://github.com/urlesistiana/v2dat
|
||||
URL:=https://github.com/kenzok8/v2dat
|
||||
DEPENDS:=$(GO_ARCH_DEPENDS)
|
||||
endef
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
From 226cb45cc97c52fc0383a5b5172a131f65921f4a Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Wed, 20 Sep 2023 20:52:27 +0800
|
||||
Subject: [PATCH 1/3] format logtime
|
||||
|
||||
---
|
||||
mlog/logger.go | 15 +++++++++++++--
|
||||
1 file changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/mlog/logger.go
|
||||
+++ b/mlog/logger.go
|
||||
@@ -1,17 +1,28 @@
|
||||
package mlog
|
||||
|
||||
-import "go.uber.org/zap"
|
||||
+import (
|
||||
+ "time"
|
||||
+
|
||||
+ "go.uber.org/zap"
|
||||
+ "go.uber.org/zap/zapcore"
|
||||
+)
|
||||
|
||||
var logger = mustInitLogger()
|
||||
|
||||
func mustInitLogger() *zap.Logger {
|
||||
- l, err := zap.NewDevelopment(zap.WithCaller(false))
|
||||
+ config := zap.NewDevelopmentConfig()
|
||||
+ config.EncoderConfig.EncodeTime = customTimeEncoder
|
||||
+ l, err := config.Build(zap.WithCaller(false))
|
||||
if err != nil {
|
||||
panic("failed to init mlog:" + err.Error())
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
+func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||
+ enc.AppendString(t.Format("2006-01-02 15:04:05"))
|
||||
+}
|
||||
+
|
||||
func L() *zap.Logger {
|
||||
return logger
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
From 0e465de6bc63d71dd7371209bbaaf9350e2fc567 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Fri, 20 Mar 2026 09:45:03 +0800
|
||||
Subject: [PATCH 2/3] v2dat: update dependencies
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
go.mod | 15 ++++++---------
|
||||
go.sum | 47 +++++++++++++++++------------------------------
|
||||
2 files changed, 23 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -1,18 +1,15 @@
|
||||
module github.com/urlesistiana/v2dat
|
||||
|
||||
-go 1.19
|
||||
+go 1.23
|
||||
|
||||
require (
|
||||
- github.com/spf13/cobra v1.6.1
|
||||
- go.uber.org/zap v1.24.0
|
||||
- google.golang.org/protobuf v1.28.1
|
||||
+ github.com/spf13/cobra v1.10.2
|
||||
+ go.uber.org/zap v1.27.1
|
||||
+ google.golang.org/protobuf v1.36.11
|
||||
)
|
||||
|
||||
require (
|
||||
- github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
- github.com/spf13/pflag v1.0.5 // indirect
|
||||
- github.com/stretchr/testify v1.8.1 // indirect
|
||||
- go.uber.org/atomic v1.10.0 // indirect
|
||||
- go.uber.org/multierr v1.9.0 // indirect
|
||||
+ github.com/spf13/pflag v1.0.10 // indirect
|
||||
+ go.uber.org/multierr v1.11.0 // indirect
|
||||
)
|
||||
--- a/go.sum
|
||||
+++ b/go.sum
|
||||
@@ -1,42 +1,29 @@
|
||||
-github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
-github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
-github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
+github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
+github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
+github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
+github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
+github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
-go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
-go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
-go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
-go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
-go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
-go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
-go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
-google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
+go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
+go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
+google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
+google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1,128 +0,0 @@
|
||||
From 0c6f9a36049423283052dfaf6eb9e211afe95c89 Mon Sep 17 00:00:00 2001
|
||||
From: sbwml <admin@cooluc.com>
|
||||
Date: Fri, 20 Mar 2026 10:11:24 +0800
|
||||
Subject: [PATCH 3/3] perf(unpack): Use memory mapping to reduce memory usage
|
||||
|
||||
Replaced `os.ReadFile` with `mmap` to avoid loading the entire geoip.dat
|
||||
or geosite.dat file into memory during unpacking. This fixes
|
||||
out-of-memory errors on low-memory devices.
|
||||
|
||||
Signed-off-by: sbwml <admin@cooluc.com>
|
||||
---
|
||||
cmd/unpack/geoip.go | 18 ++++++++++++++----
|
||||
cmd/unpack/geosite.go | 11 ++++++++++-
|
||||
go.mod | 4 +++-
|
||||
go.sum | 4 ++++
|
||||
4 files changed, 31 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/cmd/unpack/geoip.go
|
||||
+++ b/cmd/unpack/geoip.go
|
||||
@@ -3,14 +3,16 @@ package unpack
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
- "github.com/spf13/cobra"
|
||||
- "github.com/urlesistiana/v2dat/v2data"
|
||||
- "go.uber.org/zap"
|
||||
"io"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
+
|
||||
+ "github.com/edsrzf/mmap-go"
|
||||
+ "github.com/spf13/cobra"
|
||||
+ "github.com/urlesistiana/v2dat/v2data"
|
||||
+ "go.uber.org/zap"
|
||||
)
|
||||
|
||||
func newGeoIPCmd() *cobra.Command {
|
||||
@@ -34,10 +36,18 @@ func newGeoIPCmd() *cobra.Command {
|
||||
|
||||
func unpackGeoIP(args *unpackArgs) error {
|
||||
filePath, wantTags, ourDir := args.file, args.filters, args.outDir
|
||||
- b, err := os.ReadFile(filePath)
|
||||
+
|
||||
+ file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+ defer file.Close()
|
||||
+
|
||||
+ b, err := mmap.Map(file, mmap.RDONLY, 0)
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("error mapping file: %w", err)
|
||||
+ }
|
||||
+ defer b.Unmap()
|
||||
geoIPList, err := v2data.LoadGeoIPListFromDAT(b)
|
||||
if err != nil {
|
||||
return err
|
||||
--- a/cmd/unpack/geosite.go
|
||||
+++ b/cmd/unpack/geosite.go
|
||||
@@ -3,6 +3,7 @@ package unpack
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
+ "github.com/edsrzf/mmap-go"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/urlesistiana/v2dat/v2data"
|
||||
"go.uber.org/zap"
|
||||
@@ -39,10 +40,18 @@ func newGeoSiteCmd() *cobra.Command {
|
||||
|
||||
func unpackGeoSite(args *unpackArgs) error {
|
||||
filePath, suffixes, outDir := args.file, args.filters, args.outDir
|
||||
- b, err := os.ReadFile(filePath)
|
||||
+
|
||||
+ file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+ defer file.Close()
|
||||
+
|
||||
+ b, err := mmap.Map(file, mmap.RDONLY, 0)
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("error mapping file: %w", err)
|
||||
+ }
|
||||
+ defer b.Unmap()
|
||||
geoSiteList, err := v2data.LoadGeoSiteList(b)
|
||||
if err != nil {
|
||||
return err
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -1,8 +1,9 @@
|
||||
module github.com/urlesistiana/v2dat
|
||||
|
||||
-go 1.23
|
||||
+go 1.25.0
|
||||
|
||||
require (
|
||||
+ github.com/edsrzf/mmap-go v1.2.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
go.uber.org/zap v1.27.1
|
||||
google.golang.org/protobuf v1.36.11
|
||||
@@ -12,4 +13,5 @@ require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
+ golang.org/x/sys v0.42.0 // indirect
|
||||
)
|
||||
--- a/go.sum
|
||||
+++ b/go.sum
|
||||
@@ -1,6 +1,8 @@
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
+github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84=
|
||||
+github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
@@ -22,6 +24,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:2
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
+golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
Reference in new issue
Block a user