diff --git a/package/cnsztl/luci-app-openclash/Makefile b/package/cnsztl/luci-app-openclash/Makefile old mode 100755 new mode 100644 index 73d397e91d..f5842d8431 --- a/package/cnsztl/luci-app-openclash/Makefile +++ b/package/cnsztl/luci-app-openclash/Makefile @@ -1,20 +1,21 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-openclash -PKG_VERSION=0.30.0 -PKG_RELEASE:=1 -PKG_MAINTAINER:=frainzy1477&vernesong +PKG_VERSION:=0.33.2 +PKG_RELEASE:=beta +PKG_MAINTAINER:=vernesong PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) include $(INCLUDE_DIR)/package.mk define Package/$(PKG_NAME) - CATEGORY:=Utilities - SUBMENU:=Luci + CATEGORY:=LuCI + SUBMENU:=3. Applications TITLE:=LuCI support for clash PKGARCH:=all - DEPENDS:=+coreutils-nohup +bash +wget + DEPENDS:=+luci +luci-base +iptables +coreutils +coreutils-nohup +bash +wget + MAINTAINER:=vernesong endef define Package/$(PKG_NAME)/description @@ -35,11 +36,66 @@ endef define Build/Compile endef +define Package/$(PKG_NAME)/preinst +#!/bin/sh +if [ -f "/etc/config/openclash" ]; then + uci set openclash.config.enable=0 && uci commit openclash + cp "/etc/config/openclash" "/tmp/openclash.bak" 2>/dev/null + cp "/etc/config/openclash_custom_rules.list" "/tmp/openclash_custom_rules.list.bak" 2>/dev/null + cp "/etc/config/openclash_custom_hosts.list" "/tmp/openclash_custom_hosts.list.bak" 2>/dev/null +fi +endef + +define Package/$(PKG_NAME)/postinst +#!/bin/sh +rm -rf /tmp/luci* +if [ -f "/tmp/openclash.bak" ]; then + mv "/tmp/openclash.bak" "/etc/config/openclash" 2>/dev/null + mv "/tmp/openclash_custom_rules.list.bak" "/etc/config/openclash_custom_rules.list" 2>/dev/null + mv "/tmp/openclash_custom_hosts.list.bak" "/etc/config/openclash_custom_hosts.list" 2>/dev/null +fi +if [ -f "/tmp/config.yaml" ]; then + mv "/tmp/config.yaml" "/etc/openclash/config.yaml" 2>/dev/null +elif [ -f "/tmp/config.yml" ]; then + mv "/tmp/config.yml" "/etc/openclash/config.yaml" 2>/dev/null +fi +endef + +define Package/$(PKG_NAME)/prerm +#!/bin/sh +update=$(uci get openclash.config.update 2>/dev/null) +if [ "$update" != 1 ]; then + rm -rf /etc/openclash/clash 2>/dev/null + uci set openclash.config.enable=0 && uci commit openclash +else + uci set openclash.config.enable=1 && uci commit openclash +fi + cp "/etc/config/openclash" "/tmp/openclash.bak" 2>/dev/null + cp "/etc/config/openclash_custom_rules.list" "/tmp/openclash_custom_rules.list.bak" 2>/dev/null + cp "/etc/config/openclash_custom_hosts.list" "/tmp/openclash_custom_hosts.list.bak" 2>/dev/null +endef + +define Package/$(PKG_NAME)/postrm +#!/bin/sh +if [ -f "/etc/openclash/config.yaml" ]; then + mv "/etc/openclash/config.yaml" "/tmp/config.yaml" +fi +if [ -f "/etc/openclash/clash" ]; then + rm -rf /etc/openclash/config.* 2>/dev/null +else + rm -rf /etc/openclash 2>/dev/null +fi + rm -rf /tmp/openclash.log 2>/dev/null + rm -rf /tmp/openclash_start.log 2>/dev/null + rm -rf /tmp/Proxy_Group 2>/dev/null + rm -rf /tmp/openclash_last_version 2>/dev/null + rm -rf /tmp/clash_last_version 2>/dev/null +endef + define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n $(INSTALL_DATA) $(PKG_BUILD_DIR)/*.*.lmo $(1)/usr/lib/lua/luci/i18n/ $(CP) ./files/* $(1)/ - endef $(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/cnsztl/luci-app-openclash/files/etc/config/openclash b/package/cnsztl/luci-app-openclash/files/etc/config/openclash old mode 100755 new mode 100644 index 50d563035a..7117959d78 --- a/package/cnsztl/luci-app-openclash/files/etc/config/openclash +++ b/package/cnsztl/luci-app-openclash/files/etc/config/openclash @@ -2,6 +2,7 @@ config openclash 'config' option proxy_port '7892' option enable '0' + option update '0' option en_mode '0' option auto_update '0' option auto_update_time '0' @@ -9,5 +10,9 @@ config openclash 'config' option dashboard_password '123456' option rule_source '0' option enable_custom_dns '0' + option ipv6_enable '0' option enable_custom_clash_rules '0' - option other_rule_auto_update '0' \ No newline at end of file + option other_rule_auto_update '0' + option core_version '0' + option en_mode 'redir-host' + option update '0' \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/etc/config/openclash_custom_hosts.list b/package/cnsztl/luci-app-openclash/files/etc/config/openclash_custom_hosts.list new file mode 100644 index 0000000000..1180bb5f65 --- /dev/null +++ b/package/cnsztl/luci-app-openclash/files/etc/config/openclash_custom_hosts.list @@ -0,0 +1,6 @@ +# experimental hosts, support wildcard (e.g. *.clash.dev Even *.foo.*.example.com) +# static domain has a higher priority than wildcard domain (foo.example.com > *.example.com) +# NOTE: hosts don't work with `fake-ip` + +# '*.clash.dev': 127.0.0.1 +# 'alpha.clash.dev': '::1' diff --git a/package/cnsztl/luci-app-openclash/files/etc/config/openclash_custom_rules.list b/package/cnsztl/luci-app-openclash/files/etc/config/openclash_custom_rules.list old mode 100755 new mode 100644 diff --git a/package/cnsztl/luci-app-openclash/files/etc/init.d/openclash b/package/cnsztl/luci-app-openclash/files/etc/init.d/openclash index 3a779969f9..0b323626c0 100755 --- a/package/cnsztl/luci-app-openclash/files/etc/init.d/openclash +++ b/package/cnsztl/luci-app-openclash/files/etc/init.d/openclash @@ -8,26 +8,28 @@ STOP=15 CLASH="/etc/openclash/clash" CLASH_CONFIG="/etc/openclash" CRON_FILE="/etc/crontabs/root" -CONFIG_FILE="/etc/openclash/config.yml" +CONFIG_FILE="/etc/openclash/config.yaml" LOG_FILE="/tmp/openclash.log" START_LOG="/tmp/openclash_start.log" BACKPACK_FILE="/etc/openclash/config.bak" -CHANGE_FILE="/tmp/yml_change.yml" -RULE_FILE="/tmp/yml_rules.yml" -DNS_FILE="/tmp/yml_dns.yml" - +START_BACKPACK="/tmp/config.sbak" +CHANGE_FILE="/tmp/yaml_change.yaml" +RULE_FILE="/tmp/yaml_rules.yaml" +DNS_FILE="/tmp/yaml_dns.yaml" +PROXY_FILE="/tmp/yaml_proxy.yaml" +HOSTS_FILE="/etc/config/openclash_custom_hosts.list" add_cron() { - [ -z "`grep "openclash.log" "$CRON_FILE"`" ] && { - echo '0 0 * * 0 echo "" > /tmp/openclash.log' >> $CRON_FILE + [ -z "$(grep "openclash.sh" "$CRON_FILE")" ] && { + [ "$(uci get openclash.config.auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.auto_update_time 2>/dev/null) * * $(uci get openclash.config.config_update_week_time 2>/dev/null) /usr/share/openclash/openclash.sh" >> $CRON_FILE } - [ -z "`grep "openclash.sh" "$CRON_FILE"`" ] && { - [ "$(uci get openclash.config.auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.auto_update_time 2>/dev/null) * * * /usr/share/openclash/openclash.sh" >> $CRON_FILE - } - [ -z "`grep "openclash_rule.sh" "$CRON_FILE"`" ] && { + [ -z "$(grep "openclash_rule.sh" "$CRON_FILE")" ] && { [ "$(uci get openclash.config.other_rule_auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.other_rule_update_day_time 2>/dev/null) * * $(uci get openclash.config.other_rule_update_week_time 2>/dev/null) /usr/share/openclash/openclash_rule.sh" >> $CRON_FILE } + [ -z "$(grep "openclash_ipdb.sh" "$CRON_FILE")" ] && { + [ "$(uci get openclash.config.geo_auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.geo_update_day_time 2>/dev/null) * * $(uci get openclash.config.geo_update_week_time 2>/dev/null) /usr/share/openclash/openclash_ipdb.sh" >> $CRON_FILE + } crontab $CRON_FILE nohup /usr/share/openclash/openclash_watchdog.sh & } @@ -36,84 +38,117 @@ del_cron() { sed -i '/openclash.sh/d' $CRON_FILE 2>/dev/null sed -i '/openclash_rule.sh/d' $CRON_FILE 2>/dev/null + sed -i '/openclash_ipdb.sh/d' $CRON_FILE 2>/dev/null /etc/init.d/cron restart } yml_check() { + #创建启动备份 + cp "$3" "$5" + + #创建原始备份 if [ ! -f "$4" ]; then - cp "$3" "$4" + cp "$3" "$4" fi - if [ "$(grep -c '^##Custom DNS##' "$CONFIG_FILE")" -gt 0 ] && [ "$2" = 0 ]; then - cp "$4" "$3" + #自定义DNS还原 + if [ "$(grep -c '##Custom DNS##' "$3")" -gt 0 ] && [ "$2" = 0 ] && [ -f "$4" ]; then + awk '/^ {0,}nameserver:/,/Proxy:/{print}' "$4" | sed '/^Proxy:/d' >/tmp/bakdns.config 2>/dev/null + sed -i '/OpenClash-General-Settings/i\Custom DNS End' "$3" 2>/dev/null + sed -i '/^ \{0,\}nameserver:/,/^Custom DNS End$/d' "$3" 2>/dev/null + sed -i '/##Custom DNS##/r/tmp/bakdns.config' "$3" 2>/dev/null + rm -rf /tmp/bakdns.config 2>/dev/null fi + + yml_dns_check - if [ "$1" = 0 ]; then - if [ -f "$4" ]; then - [ ! -z "`grep "OpenClash-General" "$CONFIG_FILE"`" ] && { - cp "$4" "$3" - } - else - [ -z "`grep "OpenClash-General" "$CONFIG_FILE"`" ] && { - cp "$3" "$4" - } - fi - fi + #检查行首空格避免后续操作出错 + [ ! -z "$(grep "^ \{1,\}Proxy:" $3)" ] && { + sed -i "/^ \{1,\}Proxy:/c\Proxy:" "$3" + } + + [ ! -z "$(grep "^ \{1,\}Proxy Group:" $3)" ] && { + sed -i "/^ \{1,\}Proxy Group:/c\Proxy Group:" "$3" + } + + [ ! -z "$(grep "^ \{1,\}Rule:" $3)" ] && { + sed -i "/^ \{1,\}Rule:/c\Rule:" "$3" + } + + [ ! -z "$(grep "^ \{1,\}dns:" $3)" ] && { + sed -i "/^ \{1,\}dns:/c\dns:" "$3" + } + + if [ ! -z "$(grep "^ \{1,\}port:" $3)" ] || [ ! -z "$(grep "^ \{1,\}mode:" $3)" ] || [ ! -z "$(grep "^ \{1,\}log-level:" $3)" ]; then + cp "$3" /tmp/config.check 2>/dev/null + sed -i '/^dns:/,$d' /tmp/config.check 2>/dev/null + sed -i 's/^[ \t]*//' /tmp/config.check 2>/dev/null + sed -n '/^dns:/,$p' "$3" >> /tmp/config.check 2>/dev/null + mv /tmp/config.check "$3" 2>/dev/null + fi + + #添加标识 sed -i '/OpenClash-General/d' "$3" 2>/dev/null sed -i '/^Proxy:/i\#===================== OpenClash-General-Settings =====================#' "$3" 2>/dev/null } +#检查DNS设置 yml_dns_check() { - if [ "$1" -eq 53 ]; then - sed -i "/^ listen:/c\ listen: 0.0.0.0:7874" "$2" + + [ -z "$(grep '^dns:' $CONFIG_FILE)" ] && { + sed -i '/^Proxy:/i\dns:' "$CONFIG_FILE" 2>/dev/null + } + + [ -z "$(grep '^ \{0,\}nameserver:' $CONFIG_FILE)" ] && { + sed -i -e '/^Proxy:/i\ nameserver:' "$CONFIG_FILE" 2>/dev/null + sed -i "/nameserver:/a\ - tls://8.8.8.8:853" "$CONFIG_FILE" 2>/dev/null + sed -i "/nameserver:/a\ - 114.114.114.114" "$CONFIG_FILE" 2>/dev/null + } + + dns_port=$(grep "^ \{0,\}listen:" $CONFIG_FILE |awk -F ':' '{print $3}' |awk -F '#' '{print $1}' |tr -cd "[0-9]" 2>/dev/null) + if [ -z "$dns_port" ] || [ "$dns_port" -eq 53 ]; then dns_port=7874 fi - - [ -z "`grep "^dns:" $CONFIG_FILE`" ] && { - sed -i -e "/^Proxy:$/i\dns:"\ - -e "/^dns:/a\ enable: true"\ - -e "/enable: true/a\ listen: 0.0.0.0:${1}"\ - -e "/listen:/a\ enhanced-mode: redir-host"\ - -e "/enhanced-mode:/a\ nameserver:"\ - -e "/nameserver:/a\ - 114.114.114.114"\ - -e "/114.114.114.114/a\ - 119.29.29.29"\ - -e "/119.29.29.29/a\ - 223.5.5.5"\ - -e "/223.5.5.5/a\ fallback:"\ - -e "/fallback:/a\ - tls://dns.rubyfish.cn:853"\ - -e "/dns.rubyfish.cn:853/a\- tcp://1.1.1.1:53"\ - -e "/1.1.1.1:53/a\ - tcp://208.67.222.222:443"\ - -e "/208.67.222.222:443/a\ - tls://dns.google" "$2" - } + if [ ! -z "$(grep "^ \{0,\}listen:" "$CONFIG_FILE")" ]; then + sed -i "/^ \{0,\}listen:/c\ listen: 0.0.0.0:${dns_port}" "$CONFIG_FILE" 2>/dev/null + else + sed -i "/^dns:/a\ listen: 0.0.0.0:${dns_port}" "$CONFIG_FILE" 2>/dev/null + fi + } +#切割配置文件以分开处理 yml_cut() { - cp "$5" "$2" - if [ "$1" = 0 ]; then - sed -i '/^Rule:$/,$d' "$2" - sed -n '/^Rule:$/,$p' "$5" >"$3" - else - sed -i '/^Rule:$/,$d' "$2" - sed -n '/nameserver:$/,$p' "$2" >"$4" - sed -i '/nameserver:$/,$d' "$2" - sed -n '/^Rule:$/,$p' "$5" >"$3" - fi + cp "$4" "$1" + sed -i '/^Rule:/,$d' "$1" + sed -n '/^ \{0,\}nameserver:/,$p' "$1" >"$3" + sed -n '/^ \{0,\}Proxy:/,$p' "$3" >"$5" + sed -i '/^ \{0,\}nameserver:/,$d' "$1" + sed -i '/^ \{0,\}Proxy:/,$d' "$3" + sed -n '/^Rule:/,$p' "$4" >"$2" + } +#获取自定义DNS设置 yml_dns_get() { local section="$1" local dns_type="" local dns_address="" + config_get_bool "enabled" "$section" "enabled" "1" config_get "port" "$section" "port" "" config_get "type" "$section" "type" "" config_get "ip" "$section" "ip" "" config_get "group" "$section" "group" "" + if [ "$enabled" = "0" ]; then + return + fi if [ -z "$ip" ]; then return @@ -125,6 +160,8 @@ yml_dns_get() dns_type="- tls://" elif [ "$type" = "udp" ]; then dns_type="- " + elif [ "$type" = "https" ]; then + dns_type="- https://" fi if [ ! -z "$port" ] && [ ! -z "$ip" ]; then @@ -139,8 +176,7 @@ yml_dns_get() if [ "$group" = "nameserver" ]; then echo " $dns_type$dns_address" >>/etc/openclash/config.namedns else - grep "fallback:$" /etc/openclash/config.falldns 1>/dev/null - if [ "$?" -ne "0" ]; then + if [ -z "$(grep "fallback:$" /etc/openclash/config.falldns 2>/dev/null)" ]; then echo " fallback:" >/etc/openclash/config.falldns fi echo " $dns_type$dns_address" >>/etc/openclash/config.falldns @@ -151,32 +187,116 @@ yml_dns_get() } +#添加自定义DNS设置 yml_dns_custom() { - [ "$1" = 1 ] && { - echo " nameserver:" >/etc/openclash/config.namedns - config_load "openclash" - config_foreach yml_dns_get "dns_servers" - sed -i '/nameserver:$/i\##Custom DNS##' "$2" 2>/dev/null - sed -i '/OpenClash-General-Settings/i\Custom DNS End' "$2" 2>/dev/null - sed -i '/nameserver:$/,/^Custom DNS End$/d' "$2" 2>/dev/null - sed -i '/^##Custom DNS##$/r/etc/openclash/config.falldns' "$2" 2>/dev/null - sed -i '/^##Custom DNS##$/r/etc/openclash/config.namedns' "$2" 2>/dev/null - rm -rf /etc/openclash/config.namedns 2>/dev/null - rm -rf /etc/openclash/config.falldns 2>/dev/null + if [ "$1" = 1 ]; then + echo " nameserver:" >/etc/openclash/config.namedns + config_load "openclash" + config_foreach yml_dns_get "dns_servers" + sed -i '/^ \{0,\}nameserver:/i\##Custom DNS##' "$2" 2>/dev/null + sed -i '/OpenClash-General-Settings/i\Custom DNS End' "$2" 2>/dev/null + sed -i '/^ \{0,\}nameserver:/,/^Custom DNS End$/d' "$2" 2>/dev/null + sed -i '/##Custom DNS##/r/etc/openclash/config.falldns' "$2" 2>/dev/null + sed -i '/##Custom DNS##/r/etc/openclash/config.namedns' "$2" 2>/dev/null + rm -rf /etc/openclash/config.namedns 2>/dev/null + rm -rf /etc/openclash/config.falldns 2>/dev/null + else + sed -i "/^ \{0,\}nameserver:/c\ nameserver:" "$2" 2>/dev/null + sed -i "/^ \{0,\}fallback:/c\ fallback:" "$2" 2>/dev/null + if [ ! -z "$(grep "^ \{0,1\}- " $2)" ]; then + sed -i "s/^ \{0,\}- / - /" "$2" 2>/dev/null #添加参数空格 + fi + fi + +} + +#添加自定义Hosts设置 +yml_hosts_custom() +{ + if [ "$en_mode" = "redir-host" ]; then + if [ -z "$(grep '^ \{0,\}hosts:' $1)" ]; then + echo " hosts:" >>"$1" 2>/dev/null + else + if [ -z "$(grep '^ hosts:' $1)" ]; then + sed -i "/hosts:/c\ hosts:" "$1" 2>/dev/null + fi + fi + sed -i "s/^ \{0,\}/ /" "$2" 2>/dev/null #修改参数空格 + sed -i "1i\##Custom HOSTS##" "$2" 2>/dev/null + echo "##Custom HOSTS END##" >>"$2" 2>/dev/null + sed -i '/##Custom HOSTS##/,/##Custom HOSTS END##/d' "$1" 2>/dev/null + sed -i '/^ hosts:/r/etc/config/openclash_custom_hosts.list' "$1" 2>/dev/null + sed -i '/##Custom HOSTS##/d' "$2" 2>/dev/null + sed -i '/##Custom HOSTS END##/d' "$2" 2>/dev/null + else + sed -i '/^ *$/d' "$1" 2>/dev/null + lastl = `sed -n -e '/hosts:/=' "$1" 2>/dev/null` + lasthl = `sed -n '$=' "$1" 2>/dev/null` + if [ "$lastl" = "$lasthl" ]; then + sed -i '/^ \{0,\}hosts:/d' "$1" 2>/dev/null + fi + sed -i '/##Custom HOSTS##/,/##Custom HOSTS END##/d' "$1" 2>/dev/null + fi +} + +#获取认证信息 +yml_auth_get() +{ + local section="$1" + config_get_bool "enabled" "$section" "enabled" "1" + config_get "username" "$section" "username" "" + config_get "password" "$section" "password" "" + + if [ "$enabled" = "0" ]; then + return + fi + + if [ -z "$username" ] || [ -z "$password" ]; then + return + else + echo " - $username:$password" >>/etc/openclash/config.auth + fi +} + +#添加认证信息 +yml_auth_custom() +{ + if [ ! -z "$(grep "^authentication:" "$1")" ]; then + sed -i '/^dns:/i\#authentication' "$1" 2>/dev/null + sed -i '/^authentication:/,/^#authentication/d' "$1" 2>/dev/null + fi + [ -f /etc/openclash/config.auth ] && { + sed -i '/^dns:/i\authentication:' "$1" 2>/dev/null + sed -i '/^authentication:/r/etc/openclash/config.auth' "$1" 2>/dev/null + rm -rf /etc/openclash/config.auth 2>/dev/null } } - + start() { -echo "OpenClash 开始启动..." >$START_LOG -enable=$(uci get openclash.config.enable 2>/dev/null) -LOGTIME=$(date "+%Y-%m-%d %H:%M:%S") -if [ ! -f $CONFIG_FILE ] && [ -f $BACKPACK_FILE ]; then +#禁止多个实例 +status=$(ps|grep -c /etc/init.d/openclash) +[ "$status" -gt "3" ] && exit 0 + +if [ ! -f "$CONFIG_FILE" ] && [ "$(ls -l /etc/openclash/config.yml 2>/dev/null |awk '{print int($5/1024)}')" -gt 0 ]; then + mv "/etc/openclash/config.yml" "$CONFIG_FILE" +fi +if [ ! -f "$CONFIG_FILE" ] && [ -f "$BACKPACK_FILE" ]; then cp $BACKPACK_FILE $CONFIG_FILE fi -if [ "$enable" -eq 1 ] && [ -f $CONFIG_FILE ]; then - echo "第一步: 获取配置中..." >$START_LOG + +echo "OpenClash 开始启动..." >$START_LOG +enable=$(uci get openclash.config.enable 2>/dev/null) +LOGTIME=$(date "+%Y-%m-%d %H:%M:%S") +if [ "$enable" -eq 1 ] && [ -f "$CONFIG_FILE" ]; then +#检查是否存在核心文件 +[ ! -f "$CLASH" ] && { + echo "OpenClash 核心文件不存在,开始下载..." >$START_LOG + nohup /usr/share/openclash/openclash_core.sh & + exit 0 +} + echo "第一步: 获取配置..." >$START_LOG en_mode=$(uci get openclash.config.en_mode 2>/dev/null) enable_custom_dns=$(uci get openclash.config.enable_custom_dns 2>/dev/null) rule_source=$(uci get openclash.config.rule_source 2>/dev/null) @@ -184,45 +304,50 @@ if [ "$enable" -eq 1 ] && [ -f $CONFIG_FILE ]; then da_password=$(uci get openclash.config.dashboard_password 2>/dev/null) cn_port=$(uci get openclash.config.cn_port 2>/dev/null) proxy_port=$(uci get openclash.config.proxy_port 2>/dev/null) + ipv6_enable=$(uci get openclash.config.ipv6_enable 2>/dev/null) + http_port=$(uci get openclash.config.http_port 2>/dev/null) + socks_port=$(uci get openclash.config.socks_port 2>/dev/null) echo "第二步: 配置文件检查..." >$START_LOG - yml_check "$en_mode" "$enable_custom_dns" "$CONFIG_FILE" "$BACKPACK_FILE" - current_mode=$(grep "enhanced-mode:" $CONFIG_FILE |awk -F ' ' '{print $2}' 2>/dev/null) - dns_port=`grep listen: $CONFIG_FILE |awk -F ':' '{print $3}' |tr -cd "[0-9]"` - yml_dns_check "$dns_port" "$CONFIG_FILE" + yml_check "$en_mode" "$enable_custom_dns" "$CONFIG_FILE" "$BACKPACK_FILE" "$START_BACKPACK" + grep "^ \{0,\}nameserver:" $CONFIG_FILE >/dev/null 2>&1 && grep "^ \{0,\}Proxy:" $CONFIG_FILE >/dev/null 2>&1 && grep "^ \{0,\}Proxy Group:" $CONFIG_FILE >/dev/null 2>&1 && grep "^ \{0,\}Rule:" $CONFIG_FILE >/dev/null 2>&1 + if [ "$?" -ne "0" ]; then + nohup $CLASH -d "$CLASH_CONFIG" >> $LOG_FILE 2>&1 & + echo "错误: 配置文件完整性检查不通过,已自动还原配置文件,请根据日志信息对照模板格式检查修改配置文件!" >$START_LOG + mv $START_BACKPACK $CONFIG_FILE + stop + sleep 5 + echo "" >$START_LOG + else echo "第三步: 修改配置文件..." >$START_LOG - yml_cut "$enable_custom_dns" "$CHANGE_FILE" "$RULE_FILE" "$DNS_FILE" "$CONFIG_FILE" + config_load "openclash" + config_foreach yml_auth_get "authentication" + yml_auth_custom "$CONFIG_FILE" + yml_cut "$CHANGE_FILE" "$RULE_FILE" "$DNS_FILE" "$CONFIG_FILE" "$PROXY_FILE" yml_dns_custom "$enable_custom_dns" "$DNS_FILE" - sh /usr/share/openclash/yml_change.sh "$LOGTIME" "$en_mode" "$enable_custom_dns" "$da_password" "$cn_port" "$proxy_port" "$current_mode" "$CHANGE_FILE" & + yml_hosts_custom "$CHANGE_FILE" "$HOSTS_FILE" + sh /usr/share/openclash/yml_change.sh "$LOGTIME" "$en_mode" "$enable_custom_dns" "$da_password" "$cn_port" "$proxy_port" "$CHANGE_FILE" "$ipv6_enable" "$http_port" "$socks_port" & sh /usr/share/openclash/yml_rules_change.sh "$LOGTIME" "$rule_source" "$enable_custom_clash_rules" "$RULE_FILE" & wait - cat $CHANGE_FILE $DNS_FILE $RULE_FILE > $CONFIG_FILE 2>/dev/null - rm -rf /tmp/yml_* 2>/dev/null - echo "第四步: 配置文件完整性检查..." >$START_LOG - grep "^Proxy Group:$" $CONFIG_FILE 1>/dev/null && grep "^Rule:$" $CONFIG_FILE 1>/dev/null && grep "^- GEOIP" $CONFIG_FILE 1>/dev/null && grep "nameserver:$" $CONFIG_FILE 1>/dev/null - if [ "$?" -ne "0" ]; then - echo "错误: 配置文件完整性检查不通过,已自动还原配置文件,请对照模板格式检查修改配置文件..." >$START_LOG - cp $BACKPACK_FILE $CONFIG_FILE - echo "${LOGTIME} OpenClash Config Error,Please Check And Try Again" >>$LOG_FILE - sleep 20 - echo "" >$START_LOG - elif [ ! -z "`sed -n '/nameserver:/{n;p}' $CONFIG_FILE |grep 'fallback:'`" ]; then - echo "错误: 配置文件DNS选项下的Nameserver必须设置服务器,已自动还原配置文件,请修改好后再重新启动..." >$START_LOG - echo "${LOGTIME} Nameserver Must Be Set, Please Change Your Configrations In Config.yml" >>$LOG_FILE - cp $BACKPACK_FILE $CONFIG_FILE - sleep 20 + cat $CHANGE_FILE $DNS_FILE $PROXY_FILE $RULE_FILE > $CONFIG_FILE 2>/dev/null + rm -rf /tmp/yaml_* 2>/dev/null + echo "第四步: DNS设置检查..." >$START_LOG + if [ ! -z "$(sed -n '/^ \{0,\}nameserver:/{n;p}' $CONFIG_FILE |grep '^ \{0,\}fallback:')" ] || [ ! -z "$(sed -n '/^ \{0,\}nameserver:/{n;p}' $CONFIG_FILE |grep 'OpenClash-General')" ]; then + echo "错误: 配置文件DNS选项下的Nameserver必须设置服务器,已自动还原配置文件,请重新设置!" >$START_LOG + echo "${LOGTIME} Nameserver Must Be Set, Please Change Your Configrations In Config.yaml" >>$LOG_FILE + mv $START_BACKPACK $CONFIG_FILE + sleep 10 echo "" >$START_LOG else echo "第五步: 启动 Clash 主程序..." >$START_LOG - nohup $CLASH -d "$CLASH_CONFIG" > $LOG_FILE 2>&1 & + nohup $CLASH -d "$CLASH_CONFIG" >> $LOG_FILE 2>&1 & echo "第六步: 设置 OpenClash 防火墙规则..." >$START_LOG - ln -s /usr/share/openclash/web /www/openclash 2>/dev/null + ln -s /usr/share/openclash/yacd /www/openclash 2>/dev/null uci set firewall.@defaults[0].flow_offloading=1 - uci commit firewall + uci commit firewall /etc/init.d/firewall restart >/dev/null 2>&1 - lan_ip=$(uci get network.lan.ipaddr) - + iptables -t nat -N openclash iptables -t nat -N openclash_dns iptables -t nat -A openclash -d 0.0.0.0/8 -j RETURN @@ -233,6 +358,7 @@ if [ "$enable" -eq 1 ] && [ -f $CONFIG_FILE ]; then iptables -t nat -A openclash -d 192.168.0.0/16 -j RETURN iptables -t nat -A openclash -d 224.0.0.0/4 -j RETURN iptables -t nat -A openclash -d 240.0.0.0/4 -j RETURN + iptables -t nat -A openclash -p tcp --dport 22 -j ACCEPT iptables -t nat -A openclash_dns -p udp -j REDIRECT --to-ports "$dns_port" iptables -t nat -A openclash_dns -p tcp -j REDIRECT --to-ports "$dns_port" iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port" @@ -240,36 +366,56 @@ if [ "$enable" -eq 1 ] && [ -f $CONFIG_FILE ]; then iptables -t nat -I PREROUTING 1 -p udp --dport 53 -j openclash_dns iptables -t nat -A PREROUTING -p tcp -j openclash + if [ "$ipv6_enable" -eq 1 ]; then + ip6tables -t nat -N openclash + ip6tables -t nat -N openclash_dns + ip6tables -t nat -A openclash_dns -p udp -j REDIRECT --to-ports "$dns_port" + ip6tables -t nat -A openclash_dns -p tcp -j REDIRECT --to-ports "$dns_port" + ip6tables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port" + ip6tables -t nat -I PREROUTING 1 -p tcp --dport 53 -j openclash_dns + ip6tables -t nat -I PREROUTING 1 -p udp --dport 53 -j openclash_dns + ip6tables -t nat -A PREROUTING -p tcp -j openclash + fi + echo "第七步: 重启 Dnsmasq 程序..." >$START_LOG /etc/init.d/dnsmasq restart >/dev/null 2>&1 if pidof clash >/dev/null; then echo "第八步: 添加 OpenClash 计划任务,启动进程守护程序..." >$START_LOG add_cron echo "OpenClash 启动成功,请等待服务器上线!" >$START_LOG - echo "${LOGTIME} OpenClash Start Successfully" >> $LOG_FILE + echo "${LOGTIME} OpenClash Start Successful" >> $LOG_FILE sleep 5 echo "" >$START_LOG else echo "错误: OpenClash 启动失败,请到日志页面查看详细错误信息!" >$START_LOG echo "${LOGTIME} OpenClash Can Not Start, Please Check The Error Info And Try Again" >> $LOG_FILE - sleep 20 + sleep 10 echo "" >$START_LOG - stop + stop && echo "" >$START_LOG fi fi + rm -rf $START_BACKPACK 2>/dev/null + fi else - echo "错误: OpenClash 缺少配置文件,请上传或更新配置文件!" >$START_LOG - echo "${LOGTIME} config.yml Missing Or Clash Not Enable" >> $LOG_FILE - sleep 5 - echo "" >$START_LOG + if [ ! -f "$CONFIG_FILE" ]; then + echo "错误: OpenClash 缺少配置文件,请上传或更新配置文件!" >$START_LOG + echo "${LOGTIME} Config Not Found" >> $LOG_FILE + sleep 5 + echo "" >$START_LOG + else + echo "错误: 请从 OpenClash 客户端界面启动程序!" >$START_LOG + echo "${LOGTIME} OpenClash Must Be Start From The Luci Page" >> $LOG_FILE + sleep 5 + echo "" >$START_LOG + fi fi } - stop() { echo "OpenClash 开始关闭..." >$START_LOG echo "第一步: 删除 OpenClash 防火墙规则..." >$START_LOG +#ipv4 iptables -t nat -F openclash >/dev/null 2>&1 iptables -t nat -F openclash_dns >/dev/null 2>&1 @@ -280,6 +426,17 @@ stop() iptables -t nat -X openclash >/dev/null 2>&1 iptables -t nat -X openclash_dns >/dev/null 2>&1 +#ipv6 + ip6tables -t nat -F openclash >/dev/null 2>&1 + ip6tables -t nat -F openclash_dns >/dev/null 2>&1 + + nat6_clashs=$(ip6tables -nvL PREROUTING -t nat 2>/dev/null | sed 1,2d | sed -n '/openclash/=' | sort -r) + for nat6_clash in $nat6_clashs; do + ip6tables -t nat -D PREROUTING "$nat6_clash" >/dev/null 2>&1 + done + + ip6tables -t nat -X openclash >/dev/null 2>&1 + ip6tables -t nat -X openclash_dns >/dev/null 2>&1 uci set firewall.@defaults[0].flow_offloading=1 uci commit firewall @@ -291,31 +448,28 @@ stop() echo "第三步: 关闭 Clash 主程序..." >$START_LOG kill -9 "$(pidof clash|sed 's/$//g')" 2>/dev/null - echo "第四步: 删除 OpenClash 计划任务..." >$START_LOG - del_cron - - echo "第五步: 重启 Dnsmasq 程序..." >$START_LOG + echo "第四步: 重启 Dnsmasq 程序..." >$START_LOG /etc/init.d/dnsmasq restart >/dev/null 2>&1 - echo "第六步: 删除 OpenClash 残留文件..." >$START_LOG + echo "第五步:删除 OpenClash 残留文件..." >$START_LOG rule_source=$(uci get openclash.config.rule_source 2>/dev/null) if [ "$rule_source" != 0 ]; then - rm -rf /tmp/clash_rule.yml >/dev/null 2>&1 rm -rf /tmp/Proxy_Group >/dev/null 2>&1 fi enable=$(uci get openclash.config.enable 2>/dev/null) if [ "$enable" -eq 0 ]; then - rm -rf $LOG_FILE - rm -rf /www/openclash 2> /dev/null - rm -rf /tmp/openclash_last_version 2> /dev/null - sed -i '/openclash.log/d' $CRON_FILE + rm -rf $LOG_FILE 2>/dev/null + rm -rf /www/openclash 2>/dev/null + rm -rf /tmp/openclash_last_version 2>/dev/null + rm -rf /tmp/clash_last_version 2>/dev/null echo "OpenClash 关闭成功!" >$START_LOG - rm -rf $START_LOG - else - echo "OpenClash 关闭成功!" >$START_LOG + sleep 5 + rm -rf $START_LOG fi + + del_cron - echo "CLASH STOP" + echo "OpenClash Already Stop" } diff --git a/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yml b/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yaml old mode 100755 new mode 100644 similarity index 88% rename from package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yml rename to package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yaml index 499c3ad45c..2789219924 --- a/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yml +++ b/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua.yaml @@ -1,7 +1,58 @@ Rule: ##source:ConnersHua +# Feeb +- DOMAIN-KEYWORD,epochtimes,REJECT +- DOMAIN-SUFFIX,881903.com,REJECT +- DOMAIN-SUFFIX,aboluowang.com,REJECT +- DOMAIN-SUFFIX,bannedbook.org,REJECT +- DOMAIN-SUFFIX,china21.org,REJECT +- DOMAIN-SUFFIX,chinaaffairs.org,REJECT +- DOMAIN-SUFFIX,dajiyuan.com,REJECT +- DOMAIN-SUFFIX,dalianmeng.org,REJECT +- DOMAIN-SUFFIX,dkn.tv,REJECT +- DOMAIN-SUFFIX,dongtaiwang.com,REJECT +- DOMAIN-SUFFIX,edoors.com,REJECT +- DOMAIN-SUFFIX,epochweekly.com,REJECT +- DOMAIN-SUFFIX,falundafa.org,REJECT +- DOMAIN-SUFFIX,fgmtv.org,REJECT +- DOMAIN-SUFFIX,gardennetworks.com,REJECT +- DOMAIN-SUFFIX,gongyiluntan.org,REJECT +- DOMAIN-SUFFIX,gpass1.com,REJECT +- DOMAIN-SUFFIX,hrichina.org,REJECT +- DOMAIN-SUFFIX,huanghuagang.org,REJECT +- DOMAIN-SUFFIX,internetfreedom.org,REJECT +- DOMAIN-SUFFIX,kanzhongguo.com,REJECT +- DOMAIN-SUFFIX,lagranepoca.com,REJECT +- DOMAIN-SUFFIX,mh4u.org,REJECT +- DOMAIN-SUFFIX,mhradio.org,REJECT +- DOMAIN-SUFFIX,minghui.org,REJECT +- DOMAIN-SUFFIX,newrealmstudios.ca,REJECT +- DOMAIN-SUFFIX,ntdtv.com,REJECT +- DOMAIN-SUFFIX,ogate.org,REJECT +- DOMAIN-SUFFIX,open.com.hk,REJECT +- DOMAIN-SUFFIX,organcare.org.tw,REJECT +- DOMAIN-SUFFIX,qxbbs.org,REJECT +- DOMAIN-SUFFIX,renminbao.com,REJECT +- DOMAIN-SUFFIX,secretchina.com,REJECT +- DOMAIN-SUFFIX,shenyun.com,REJECT +- DOMAIN-SUFFIX,shenyunperformingarts.org,REJECT +- DOMAIN-SUFFIX,shenzhoufilm.com,REJECT +- DOMAIN-SUFFIX,soundofhope.org,REJECT +- DOMAIN-SUFFIX,theepochtimes.com,REJECT +- DOMAIN-SUFFIX,tiandixing.org,REJECT +- DOMAIN-SUFFIX,tuidang.org,REJECT +- DOMAIN-SUFFIX,velkaepocha.sk,REJECT +- DOMAIN-SUFFIX,watchinese.com,REJECT +- DOMAIN-SUFFIX,wixsite.com,REJECT +- DOMAIN-SUFFIX,wujie.net,REJECT +- DOMAIN-SUFFIX,wujieliulan.com,REJECT +- DOMAIN-SUFFIX,xinsheng.net,REJECT +- DOMAIN-SUFFIX,zhengjian.org,REJECT +- DOMAIN-SUFFIX,zhuichaguoji.org,REJECT + # Internet Service Provider Hijacking Protection 运营商劫持保护 - DOMAIN-SUFFIX,17gouwuba.com,Hijacking +- DOMAIN-SUFFIX,186078.com,Hijacking - DOMAIN-SUFFIX,189zj.cn,Hijacking - DOMAIN-SUFFIX,285680.com,Hijacking - DOMAIN-SUFFIX,3721zh.com,Hijacking @@ -48,6 +99,7 @@ Rule: - DOMAIN-SUFFIX,jdkic.com,Hijacking - DOMAIN-SUFFIX,jiubuhua.com,Hijacking - DOMAIN-SUFFIX,jwg365.cn,Hijacking +- DOMAIN-SUFFIX,kawo77.com,Hijacking - DOMAIN-SUFFIX,kualianyingxiao.cn,Hijacking - DOMAIN-SUFFIX,kumihua.com,Hijacking - DOMAIN-SUFFIX,linktech.cn,Hijacking @@ -56,6 +108,8 @@ Rule: - DOMAIN-SUFFIX,minisplat.cn,Hijacking - DOMAIN-SUFFIX,mkitgfs.com,Hijacking - DOMAIN-SUFFIX,mlnbike.com,Hijacking +- DOMAIN-SUFFIX,mobjump.com,Hijacking +- DOMAIN-SUFFIX,nbkbgd.cn,Hijacking - DOMAIN-SUFFIX,newapi.com,Hijacking - DOMAIN-SUFFIX,pinzhitmall.com,Hijacking - DOMAIN-SUFFIX,poppyta.com,Hijacking @@ -129,6 +183,7 @@ Rule: - IP-CIDR,115.182.16.79/32,Hijacking - IP-CIDR,118.144.88.126/32,Hijacking - IP-CIDR,118.144.88.215/32,Hijacking +- IP-CIDR,118.144.88.216/32,Hijacking - IP-CIDR,120.76.189.132/32,Hijacking - IP-CIDR,124.14.21.147/32,Hijacking - IP-CIDR,124.14.21.151/32,Hijacking @@ -214,6 +269,9 @@ Rule: - DOMAIN-SUFFIX,nflximg.net,ForeignMedia - DOMAIN-SUFFIX,nflxso.net,ForeignMedia - DOMAIN-SUFFIX,nflxvideo.net,ForeignMedia +# > Pornhub +- DOMAIN-SUFFIX,phncdn.com,ForeignMedia +- DOMAIN-SUFFIX,pornhub.com,ForeignMedia # > Amazon Prime Video (US|JP) # USER-AGENT,InstantVideo.US*,ForeignMedia # USER-AGENT,Prime%20Video*,ForeignMedia @@ -234,6 +292,7 @@ Rule: # > Hulu - DOMAIN-SUFFIX,hulu.com,ForeignMedia - DOMAIN-SUFFIX,huluim.com,ForeignMedia +- DOMAIN-SUFFIX,hulustream.com,ForeignMedia # > PBS # USER-AGENT,PBS*,ForeignMedia - DOMAIN-SUFFIX,pbs.org,ForeignMedia @@ -254,6 +313,7 @@ Rule: - DOMAIN,videos-f.jwpsrv.com,ForeignMedia # > ViuTV # USER-AGENT,ViuTV*,ForeignMedia +- DOMAIN-SUFFIX,nowe.com,ForeignMedia - DOMAIN-SUFFIX,viu.tv,ForeignMedia - DOMAIN,api.viu.now.com,ForeignMedia # > (JP) @@ -276,6 +336,10 @@ Rule: - DOMAIN-SUFFIX,bbci.co.uk,ForeignMedia - DOMAIN-KEYWORD,bbcfmt,ForeignMedia - DOMAIN-KEYWORD,uk-live,ForeignMedia +# > All4 +# USER-AGENT,All4*,ForeignMedia +- DOMAIN-SUFFIX,c4assets.com,ForeignMedia +- DOMAIN-SUFFIX,channel4.com,ForeignMedia # > (TW) # > Bahamut # USER-AGENT,Anime*,ForeignMedia @@ -379,6 +443,10 @@ Rule: - DOMAIN-SUFFIX,line-apps.com,PROXY - DOMAIN-SUFFIX,line-scdn.net,PROXY - DOMAIN-SUFFIX,naver.jp,PROXY +- IP-CIDR,103.2.30.0/23,PROXY +- IP-CIDR,125.209.208.0/20,PROXY +- IP-CIDR,147.92.128.0/17,PROXY +- IP-CIDR,203.104.144.0/21,PROXY # > Other - DOMAIN-SUFFIX,4shared.com,PROXY - DOMAIN-SUFFIX,881903.com,PROXY @@ -389,6 +457,7 @@ Rule: - DOMAIN-SUFFIX,amazon.co.jp,PROXY - DOMAIN-SUFFIX,apigee.com,PROXY - DOMAIN-SUFFIX,apk-dl.com,PROXY +- DOMAIN-SUFFIX,apkfind.com,PROXY - DOMAIN-SUFFIX,apkmirror.com,PROXY - DOMAIN-SUFFIX,apkmonk.com,PROXY - DOMAIN-SUFFIX,apkpure.com,PROXY @@ -413,6 +482,7 @@ Rule: - DOMAIN-SUFFIX,bloglovin.com,PROXY - DOMAIN-SUFFIX,bloomberg.cn,PROXY - DOMAIN-SUFFIX,bloomberg.com,PROXY +- DOMAIN-SUFFIX,blubrry.com,PROXY - DOMAIN-SUFFIX,book.com.tw,PROXY - DOMAIN-SUFFIX,booklive.jp,PROXY - DOMAIN-SUFFIX,books.com.tw,PROXY @@ -422,6 +492,7 @@ Rule: - DOMAIN-SUFFIX,bwh1.net,PROXY - DOMAIN-SUFFIX,castbox.fm,PROXY - DOMAIN-SUFFIX,cbc.ca,PROXY +- DOMAIN-SUFFIX,cccat.cc,PROXY - DOMAIN-SUFFIX,cdw.com,PROXY - DOMAIN-SUFFIX,change.org,PROXY - DOMAIN-SUFFIX,ck101.com,PROXY @@ -547,6 +618,7 @@ Rule: - DOMAIN-SUFFIX,ok.ru,PROXY - DOMAIN-SUFFIX,okex.com,PROXY - DOMAIN-SUFFIX,orientaldaily.com.my,PROXY +- DOMAIN-SUFFIX,overcast.fm,PROXY - DOMAIN-SUFFIX,paltalk.com,PROXY - DOMAIN-SUFFIX,pbxes.com,PROXY - DOMAIN-SUFFIX,pcdvd.com.tw,PROXY @@ -556,7 +628,6 @@ Rule: - DOMAIN-SUFFIX,pixiv.net,PROXY - DOMAIN-SUFFIX,player.fm,PROXY - DOMAIN-SUFFIX,plurk.com,PROXY -- DOMAIN-SUFFIX,pornhub.com,PROXY - DOMAIN-SUFFIX,prism-break.org,PROXY - DOMAIN-SUFFIX,proxifier.com,PROXY - DOMAIN-SUFFIX,pts.org.tw,PROXY @@ -578,17 +649,20 @@ Rule: - DOMAIN-SUFFIX,scribd.com,PROXY - DOMAIN-SUFFIX,seatguru.com,PROXY - DOMAIN-SUFFIX,shadowsocks.org,PROXY +- DOMAIN-SUFFIX,shopee.tw,PROXY - DOMAIN-SUFFIX,slideshare.net,PROXY - DOMAIN-SUFFIX,softfamous.com,PROXY - DOMAIN-SUFFIX,soundcloud.com,PROXY - DOMAIN-SUFFIX,startpage.com,PROXY - DOMAIN-SUFFIX,steamcommunity.com,PROXY - DOMAIN-SUFFIX,steemit.com,PROXY +- DOMAIN-SUFFIX,steemitwallet.com,PROXY - DOMAIN-SUFFIX,t66y.com,PROXY - DOMAIN-SUFFIX,tapatalk.com,PROXY - DOMAIN-SUFFIX,teco-hk.org,PROXY - DOMAIN-SUFFIX,teco-mo.org,PROXY - DOMAIN-SUFFIX,teddysun.com,PROXY +- DOMAIN-SUFFIX,theguardian.com,PROXY - DOMAIN-SUFFIX,theinitium.com,PROXY - DOMAIN-SUFFIX,tineye.com,PROXY - DOMAIN-SUFFIX,torproject.org,PROXY @@ -614,14 +688,18 @@ Rule: - DOMAIN-SUFFIX,whoer.net,PROXY - DOMAIN-SUFFIX,wikimapia.org,PROXY - DOMAIN-SUFFIX,wikipedia.org,PROXY +- DOMAIN-SUFFIX,winudf.com,PROXY - DOMAIN-SUFFIX,wire.com,PROXY - DOMAIN-SUFFIX,workflow.is,PROXY - DOMAIN-SUFFIX,worldcat.org,PROXY - DOMAIN-SUFFIX,wsj.com,PROXY - DOMAIN-SUFFIX,wsj.net,PROXY - DOMAIN-SUFFIX,xboxlive.com,PROXY +- DOMAIN-SUFFIX,xhamster.com,PROXY +- DOMAIN-SUFFIX,xnxx.com,PROXY - DOMAIN-SUFFIX,xvideos.com,PROXY - DOMAIN-SUFFIX,yahoo.com,PROXY +- DOMAIN-SUFFIX,yandex.ru,PROXY - DOMAIN-SUFFIX,yesasia.com,PROXY - DOMAIN-SUFFIX,yes-news.com,PROXY - DOMAIN-SUFFIX,yomiuri.co.jp,PROXY @@ -688,21 +766,32 @@ Rule: # (The Most Popular Sites) # > Apple -# > Apple URL Shortener +# >> Apple URL Shortener - DOMAIN-SUFFIX,appsto.re,PROXY -# > TestFlight +# >> TestFlight - DOMAIN,beta.itunes.apple.com,PROXY -# > iBooks Store download +- DOMAIN,testflight.apple.com,PROXY +# >> iBooks Store download - DOMAIN,books.itunes.apple.com,PROXY -# > iTunes Store Moveis Trailers +# >> iTunes Store Moveis Trailers - DOMAIN,hls.itunes.apple.com,PROXY -# App Store Preview +# >> App Store Preview +- DOMAIN,apps.apple.com,PROXY - DOMAIN,itunes.apple.com,PROXY -# > Spotlight +# >> Spotlight - DOMAIN,api-glb-sea.smoot.apple.com,PROXY -# > Dictionary +# >> Dictionary - DOMAIN,lookup-api.apple.com,PROXY # PROCESS-NAME,LookupViewService,PROXY +# >> Apple News and Apple Map TOMTOM Version +- DOMAIN,gspe1-ssl.ls.apple.com,PROXY +# USER-AGENT,AppleNews*,PROXY +# USER-AGENT,com.apple.news*,PROXY +- DOMAIN-SUFFIX,apple.news,PROXY +- DOMAIN,news-client.apple.com,PROXY +- DOMAIN,news-edge.apple.com,PROXY +- DOMAIN,news-events.apple.com,PROXY +- DOMAIN,apple.comscoreresearch.com,PROXY # > Google - DOMAIN-SUFFIX,abc.xyz,PROXY - DOMAIN-SUFFIX,android.com,PROXY @@ -795,6 +884,7 @@ Rule: - DOMAIN-SUFFIX,signal.org,PROXY - DOMAIN-SUFFIX,sparknotes.com,PROXY - DOMAIN-SUFFIX,streetvoice.com,PROXY +- DOMAIN-SUFFIX,supertop.co,PROXY - DOMAIN-SUFFIX,ttvnw.net,PROXY - DOMAIN-SUFFIX,tv.com,PROXY - DOMAIN-SUFFIX,twitchcdn.net,PROXY @@ -808,29 +898,17 @@ Rule: - DOMAIN-SUFFIX,yimg.com,PROXY # China Area Network -# > App Store Download || iBooks Sample -- DOMAIN-SUFFIX,itunes.apple.com,Apple -# > Apple Music -- DOMAIN,aod.itunes.apple.com,Apple -- DOMAIN,audio.itunes.apple.com,Apple -- DOMAIN,audio-ssl.itunes.apple.com,Apple -- DOMAIN,streamingaudio.itunes.apple.com,Apple -# > Apple TV -- DOMAIN,ocvideo.apple.com,Apple -# > Apple News and Apple Map TOMTOM Version -- DOMAIN,gspe1-ssl.ls.apple.com,Apple -# PROCESS-NAME,News,Apple # > Apple - DOMAIN-SUFFIX,aaplimg.com,Apple -- DOMAIN-SUFFIX,apple.co,DIRECT -- DOMAIN-SUFFIX,apple.com,DIRECT -- DOMAIN-SUFFIX,appstore.com,DIRECT +- DOMAIN-SUFFIX,apple.co,Apple +- DOMAIN-SUFFIX,apple.com,Apple +- DOMAIN-SUFFIX,appstore.com,Apple - DOMAIN-SUFFIX,cdn-apple.com,Apple -- DOMAIN-SUFFIX,crashlytics.com,DIRECT -- DOMAIN-SUFFIX,icloud.com,DIRECT +- DOMAIN-SUFFIX,crashlytics.com,Apple +- DOMAIN-SUFFIX,icloud.com,Apple - DOMAIN-SUFFIX,icloud-content.com,Apple -- DOMAIN-SUFFIX,me.com,DIRECT -- DOMAIN-SUFFIX,mzstatic.com,DIRECT +- DOMAIN-SUFFIX,me.com,Apple +- DOMAIN-SUFFIX,mzstatic.com,Apple # > Microsoft - DOMAIN-SUFFIX,microsoft.com,DIRECT - DOMAIN-SUFFIX,msecnd.net,DIRECT @@ -860,6 +938,7 @@ Rule: - DOMAIN-SUFFIX,qq.com,DIRECT - DOMAIN-SUFFIX,tencent.com,DIRECT # > Alibaba +# USER-AGENT,%E4%BC%98%E9%85%B7*,DIRECT - DOMAIN-SUFFIX,alibaba.com,DIRECT - DOMAIN-SUFFIX,alicdn.com,DIRECT - DOMAIN-SUFFIX,alikunlun.com,DIRECT @@ -874,13 +953,18 @@ Rule: - DOMAIN-SUFFIX,xiami.com,DIRECT - DOMAIN-SUFFIX,xiami.net,DIRECT # > NetEase +# USER-AGENT,NeteaseMusic*,DIRECT +# USER-AGENT,%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90*,DIRECT - DOMAIN-SUFFIX,163.com,DIRECT - DOMAIN-SUFFIX,126.net,DIRECT - DOMAIN-SUFFIX,127.net,DIRECT - DOMAIN-SUFFIX,163yun.com,DIRECT - DOMAIN-SUFFIX,lofter.com,DIRECT +- DOMAIN-SUFFIX,ydstatic.com,DIRECT # > Sohu - DOMAIN-SUFFIX,sohu.com,DIRECT +- DOMAIN-SUFFIX,sohucs.com,DIRECT +- DOMAIN-SUFFIX,sohu-inc.com,DIRECT - DOMAIN-SUFFIX,v-56.com,DIRECT # > Sina - DOMAIN-SUFFIX,weibo.com,DIRECT @@ -907,8 +991,10 @@ Rule: # > Meitu - DOMAIN-SUFFIX,meitu.com,DIRECT - DOMAIN-SUFFIX,meitudata.com,DIRECT +- DOMAIN-SUFFIX,meitustat.com,DIRECT - DOMAIN-SUFFIX,meipai.com,DIRECT # > YYeTs +# USER-AGENT,YYeTs*,DIRECT - DOMAIN-SUFFIX,jstucdn.com,DIRECT - DOMAIN-SUFFIX,zimuzu.io,DIRECT - DOMAIN-SUFFIX,zimuzu.tv,DIRECT @@ -930,8 +1016,10 @@ Rule: # > ChinaNet - DOMAIN-SUFFIX,21cn.com,DIRECT # > ByteDance +- DOMAIN-SUFFIX,feiliao.com,DIRECT - DOMAIN-SUFFIX,pstatp.com,DIRECT - DOMAIN-SUFFIX,snssdk.com,DIRECT +- DOMAIN-SUFFIX,iesdouyin.com,DIRECT - DOMAIN-SUFFIX,toutiao.com,DIRECT # > 360 - DOMAIN-SUFFIX,qhres.com,DIRECT @@ -960,12 +1048,15 @@ Rule: - DOMAIN,speedtest.macpaw.com,DIRECT # > Other - DOMAIN-SUFFIX,cn,DIRECT +- DOMAIN-SUFFIX,beitaichufang.com,DIRECT - DOMAIN-SUFFIX,cailianpress.com,DIRECT +- DOMAIN-SUFFIX,chunyu.mobi,DIRECT - DOMAIN-SUFFIX,chushou.tv,DIRECT - DOMAIN-SUFFIX,cloudflare.com,DIRECT - DOMAIN-SUFFIX,cmbchina.com,DIRECT - DOMAIN-SUFFIX,cmbimg.com,DIRECT - DOMAIN-SUFFIX,dfcfw.com,DIRECT +- DOMAIN-SUFFIX,douban.com,DIRECT - DOMAIN-SUFFIX,doubanio.com,DIRECT - DOMAIN-SUFFIX,douyu.com,DIRECT - DOMAIN-SUFFIX,dxycdn.com,DIRECT @@ -973,21 +1064,29 @@ Rule: - DOMAIN-SUFFIX,futunn.com,DIRECT - DOMAIN-SUFFIX,geilicdn.com,DIRECT - DOMAIN-SUFFIX,hicloud.com,DIRECT +- DOMAIN-SUFFIX,huya.com,DIRECT - DOMAIN-SUFFIX,infinitynewtab.com,DIRECT - DOMAIN-SUFFIX,ithome.com,DIRECT +- DOMAIN-SUFFIX,keepcdn.com,DIRECT - DOMAIN-SUFFIX,kkmh.com,DIRECT - DOMAIN-SUFFIX,ksosoft.com,DIRECT +- DOMAIN-SUFFIX,luojilab.com,DIRECT - DOMAIN-SUFFIX,maoyun.tv,DIRECT - DOMAIN-SUFFIX,meituan.net,DIRECT - DOMAIN-SUFFIX,mobike.com,DIRECT - DOMAIN-SUFFIX,mubu.com,DIRECT - DOMAIN-SUFFIX,myzaker.com,DIRECT +- DOMAIN-SUFFIX,nvidia.com,DIRECT - DOMAIN-SUFFIX,paypal.com,DIRECT - DOMAIN-SUFFIX,paypalobjects.com,DIRECT +- DOMAIN-SUFFIX,ronghub.com,DIRECT - DOMAIN-SUFFIX,ruguoapp.com,DIRECT - DOMAIN-SUFFIX,smzdm.com,DIRECT - DOMAIN-SUFFIX,snapdrop.net,DIRECT +- DOMAIN-SUFFIX,sogo.com,DIRECT - DOMAIN-SUFFIX,sogou.com,DIRECT +- DOMAIN-SUFFIX,sogoucdn.com,DIRECT +- DOMAIN-SUFFIX,sspai.com,DIRECT - DOMAIN-SUFFIX,teamviewer.com,DIRECT - DOMAIN-SUFFIX,tianyancha.com,DIRECT - DOMAIN-SUFFIX,udacity.com,DIRECT @@ -999,8 +1098,6 @@ Rule: - DOMAIN-SUFFIX,zhihu.com,DIRECT - DOMAIN-SUFFIX,zhimg.com,DIRECT - DOMAIN-SUFFIX,zhuihd.com,DIRECT -# USER-AGENT,NeteaseMusic*,DIRECT -# USER-AGENT,%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90*,DIRECT # Local Area Network - DOMAIN-SUFFIX,local,DIRECT @@ -1053,4 +1150,4 @@ Rule: # GeoIP China - GEOIP,CN,DIRECT -- MATCH,Final \ No newline at end of file +- MATCH,Final diff --git a/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yml b/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yaml old mode 100755 new mode 100644 similarity index 99% rename from package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yml rename to package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yaml index cd9299a22b..47cdc0140c --- a/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yml +++ b/package/cnsztl/luci-app-openclash/files/etc/openclash/ConnersHua_return.yaml @@ -76,4 +76,4 @@ Rule: - GEOIP,CN,PROXY -- MATCH,DIRECT \ No newline at end of file +- MATCH,DIRECT diff --git a/package/cnsztl/luci-app-openclash/files/etc/openclash/Country.mmdb b/package/cnsztl/luci-app-openclash/files/etc/openclash/Country.mmdb old mode 100755 new mode 100644 index c5260d74f6..bd5278cad1 Binary files a/package/cnsztl/luci-app-openclash/files/etc/openclash/Country.mmdb and b/package/cnsztl/luci-app-openclash/files/etc/openclash/Country.mmdb differ diff --git a/package/cnsztl/luci-app-openclash/files/etc/openclash/default.yaml b/package/cnsztl/luci-app-openclash/files/etc/openclash/default.yaml new file mode 100644 index 0000000000..b08adb3804 --- /dev/null +++ b/package/cnsztl/luci-app-openclash/files/etc/openclash/default.yaml @@ -0,0 +1,159 @@ +# Copyright (c) 2018 Dreamacro + +# port of HTTP +port: 7890 # 此项将被接管 + +# port of SOCKS5 +socks-port: 7891 # 此项将被接管 + +# redir port for Linux and macOS +redir-port: 7892 # 此项将被接管 + +allow-lan: true # 此项将被接管为true + +# Rule / Global/ Direct (default is Rule) +mode: Rule + +# set log level to stdout (default is info) +# info / warning / error / debug / silent +log-level: info + +# A RESTful API for clash +external-controller: 0.0.0.0:9090 # 此项将被接管 + +# you can put the static web resource (such as clash-dashboard) to a directory, and clash would serve in `${API}/ui` +# input is a relative path to the configuration directory or an absolute path +external-ui: "/usr/share/openclash/dashboard" # 此项将被接管 + +# Secret for RESTful API (Optional) +secret: '123456' # 此项将被接管 + +# experimental feature +experimental: + ignore-resolve-fail: true # ignore dns resolve fail, default value is true + +# authentication of local SOCKS5/HTTP(S) server +authentication: # 此项将被接管 + - "user1:pass1" + - "user2:pass2" + +dns: # 此参数必须保留,不能删除,如订阅配置无包括此项的所有DNS设置,OpenClash将自动添加 + enable: true # set true to enable dns (default is false) # 此项将被接管为true + ipv6: false # default is false # 此项将被接管 + listen: 0.0.0.0:53 # 端口为53时将被接管为7874 + enhanced-mode: redir-host # or fake-ip # 此项可被接管 + fake-ip-range: 198.18.0.1/16 # if you don't know what it is, don't change it # 此项将被接管 +# experimental hosts, support wildcard (e.g. *.clash.dev Even *.foo.*.example.com) +# static domain has a higher priority than wildcard domain (foo.example.com > *.example.com) +# NOTE: hosts don't work with `fake-ip` +# hosts: +# '*.clash.dev': 127.0.0.1 +# 'alpha.clash.dev': '::1' + nameserver: # 此参数必须保留,不能删除 + - 114.114.114.114 + - tls://dns.rubyfish.cn:853 # dns over tls + - https://1.1.1.1/dns-query # dns over https + fallback: # concurrent request with nameserver, fallback used when GEOIP country isn't CN + - tcp://1.1.1.1 + +# 以上设置您可直接覆盖到配置文件,无需更改 +# Openclash 不会对下方服务器设置进行任何更改,请确保设置正确 + +Proxy: # 此参数必须保留,不能删除 + +# shadowsocks +# The types of cipher are consistent with go-shadowsocks2 +# support AEAD_AES_128_GCM AEAD_AES_192_GCM AEAD_AES_256_GCM AEAD_CHACHA20_POLY1305 AES-128-CTR AES-192-CTR AES-256-CTR AES-128-CFB AES-192-CFB AES-256-CFB CHACHA20-IETF XCHACHA20 +# In addition to what go-shadowsocks2 supports, it also supports chacha20 rc4-md5 xchacha20-ietf-poly1305 +- { name: "ss1", type: ss, server: server, port: 443, cipher: AEAD_CHACHA20_POLY1305, password: "password", udp: true } + +# old obfs configuration remove after prerelease +- name: "ss2" + type: ss + server: server + port: 443 + cipher: AEAD_CHACHA20_POLY1305 + password: "password" + plugin: obfs + plugin-opts: + mode: tls # or http + # host: bing.com + +- name: "ss3" + type: ss + server: server + port: 443 + cipher: AEAD_CHACHA20_POLY1305 + password: "password" + plugin: v2ray-plugin + plugin-opts: + mode: websocket # no QUIC now + # tls: true # wss + # skip-cert-verify: true + # host: bing.com + # path: "/" + # headers: + # custom: value + +# vmess +# cipher support auto/aes-128-gcm/chacha20-poly1305/none +- { name: "vmess", type: vmess, server: server, port: 443, uuid: uuid, alterId: 32, cipher: auto } +# with tls +- { name: "vmess", type: vmess, server: server, port: 443, uuid: uuid, alterId: 32, cipher: auto, tls: true } +# with tls and skip-cert-verify +- { name: "vmess", type: vmess, server: server, port: 443, uuid: uuid, alterId: 32, cipher: auto, tls: true, skip-cert-verify: true } +# with ws-path and ws-headers +- { name: "vmess", type: vmess, server: server, port: 443, uuid: uuid, alterId: 32, cipher: auto, network: ws, ws-path: /path, ws-headers: { Host: v2ray.com } } +# with ws + tls +- { name: "vmess", type: vmess, server: server, port: 443, uuid: uuid, alterId: 32, cipher: auto, network: ws, ws-path: /path, tls: true } + +# socks5 +- { name: "socks", type: socks5, server: server, port: 443 } +# socks5 with authentication +- { name: "socks", type: socks5, server: server, port: 443, username: "username", password: "password" } +# with tls +- { name: "socks", type: socks5, server: server, port: 443, tls: true } +# with tls and skip-cert-verify +- { name: "socks", type: socks5, server: server, port: 443, tls: true, skip-cert-verify: true } + +# http +- { name: "http", type: http, server: server, port: 443 } +# http with authentication +- { name: "http", type: http, server: server, port: 443, username: "username", password: "password" } +# with tls (https) +- { name: "http", type: http, server: server, port: 443, tls: true } +# with tls (https) and skip-cert-verify +- { name: "http", type: http, server: server, port: 443, tls: true, skip-cert-verify: true } + +# Openclash 不会对下方策略组设置进行任何更改,请确保设置正确 + +Proxy Group: # 此参数必须保留,不能删除 + +# url-test select which proxy will be used by benchmarking speed to a URL. +- { name: "auto", type: url-test, proxies: ["ss1", "ss2", "vmess1"], url: "http://www.gstatic.com/generate_204", interval: 300 } + +# fallback select an available policy by priority. The availability is tested by accessing an URL, just like an auto url-test group. +- { name: "fallback-auto", type: fallback, proxies: ["ss1", "ss2", "vmess1"], url: "http://www.gstatic.com/generate_204", interval: 300 } + +# load-balance: The request of the same eTLD will be dial on the same proxy. +- { name: "load-balance", type: load-balance, proxies: ["ss1", "ss2", "vmess1"], url: "http://www.gstatic.com/generate_204", interval: 300 } + +# select is used for selecting proxy or proxy group +# you can use RESTful API to switch proxy, is recommended for use in GUI. +- { name: "Proxy", type: select, proxies: ["ss1", "ss2", "vmess1", "auto"] } + +Rule: # 此参数必须保留,不能删除 +# 如果您将一直使用第三方规则,下方可以留空。 +- DOMAIN-SUFFIX,google.com,auto +- DOMAIN-KEYWORD,google,auto +- DOMAIN,google.com,auto +- DOMAIN-SUFFIX,ad.com,REJECT +- IP-CIDR,127.0.0.0/8,DIRECT +# rename SOURCE-IP-CIDR and would remove after prerelease +- SRC-IP-CIDR,192.168.1.201/32,DIRECT +- GEOIP,CN,DIRECT +- DST-PORT,80,DIRECT +- SRC-PORT,7777,DIRECT +# FINAL would remove after prerelease +# you also can use `FINAL,Proxy` or `FINAL,,Proxy` now +- MATCH,auto \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yml b/package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yaml old mode 100755 new mode 100644 similarity index 99% rename from package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yml rename to package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yaml index e4c05f9924..ceb4be95ed --- a/package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yml +++ b/package/cnsztl/luci-app-openclash/files/etc/openclash/lhie1.yaml @@ -571,7 +571,6 @@ Rule: - DOMAIN-SUFFIX,rqd.qq.com,AdBlock - DOMAIN,btrace.qq.com,AdBlock - DOMAIN,mtrace.qq.com,AdBlock -- DOMAIN,oth.eve.mdt.qq.com,AdBlock - DOMAIN,pingma.qq.com,AdBlock - DOMAIN,pingtcss.qq.com,AdBlock - DOMAIN,splashqqlive.gtimg.com,AdBlock @@ -781,15 +780,15 @@ Rule: #USER-AGENT,AppleNews*,Proxy # > Apple - DOMAIN-SUFFIX,aaplimg.com,Apple -- DOMAIN-SUFFIX,apple.co,Domestic -- DOMAIN-SUFFIX,apple.com,Domestic -- DOMAIN-SUFFIX,appstore.com,Domestic +- DOMAIN-SUFFIX,apple.co,Apple +- DOMAIN-SUFFIX,apple.com,Apple +- DOMAIN-SUFFIX,appstore.com,Apple - DOMAIN-SUFFIX,cdn-apple.com,Apple -- DOMAIN-SUFFIX,crashlytics.com,Domestic -- DOMAIN-SUFFIX,icloud.com,Domestic +- DOMAIN-SUFFIX,crashlytics.com,Apple +- DOMAIN-SUFFIX,icloud.com,Apple - DOMAIN-SUFFIX,icloud-content.com,Apple -- DOMAIN-SUFFIX,me.com,Domestic -- DOMAIN-SUFFIX,mzstatic.com,Domestic +- DOMAIN-SUFFIX,me.com,Apple +- DOMAIN-SUFFIX,mzstatic.com,Apple # > Microsoft - DOMAIN-SUFFIX,microsoft.com,Domestic - DOMAIN-SUFFIX,windows.net,Domestic @@ -895,8 +894,6 @@ Rule: # > ChinaNetCenter - DOMAIN-SUFFIX,chinanetcenter.com,Domestic - DOMAIN-SUFFIX,wangsu.com,Domestic -# > CloudFlare -- DOMAIN-SUFFIX,cloudflare.com,Domestic # > IP Query - DOMAIN-SUFFIX,ipip.net,Domestic - DOMAIN-SUFFIX,ip.cn,Domestic diff --git a/package/cnsztl/luci-app-openclash/files/etc/openclash/openclash_version b/package/cnsztl/luci-app-openclash/files/etc/openclash/openclash_version old mode 100755 new mode 100644 index f52ff5208c..2b93b062d3 --- a/package/cnsztl/luci-app-openclash/files/etc/openclash/openclash_version +++ b/package/cnsztl/luci-app-openclash/files/etc/openclash/openclash_version @@ -1,2 +1,2 @@ -version:v0.30.0 -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmAAAABTCAMAAAAPxEvIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxMjFFNEYyQzhBREMxMUU5ODgyQkM5NTY1QURBMDk4MCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxMjFFNEYyRDhBREMxMUU5ODgyQkM5NTY1QURBMDk4MCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjEyMUU0RjJBOEFEQzExRTk4ODJCQzk1NjVBREEwOTgwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjEyMUU0RjJCOEFEQzExRTk4ODJCQzk1NjVBREEwOTgwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+H/iAugAAAKtQTFRFRkZGEIHCBlWChLXRo8je1dXVCHm6xMTEBHW2v9rqqampeHh4gYGBDH2+5ubmAXKzXpOymJiYCWGTPDw8bGxs9PT0tra2aq7VAnS0DoDAEoPELo7F0eTvCnu8R5vLKGyTBmym4O30B3e4Mnuk8Pb5G4TACXOvGnCgUlJSVVVVUVFRWFhYWVlZWlpaX19fXV1dXFxcTU1NUFBQTk5OW1tbXl5eT09P////////CHQSRAAAADl0Uk5T//////////////////////////////////////////////////////////////////////////8AOqxlQAAAEntJREFUeNrsnIly4roShhXAGGxC8AZhEhNDCGGZ4R7gTJL3f7IrdUvW4gWTkCKHctdMVWy1tfXnX7IsQz7Q+k5vW9tl7PnX1dmkOeVgEcTLq8NcA3ZeG00lYHZYR7kG7Nz20BKA2XWMLwvYzXUS9quFgNl/a7uovf76db2EkY9+WIf4svZ8tYA9TClgXh3hGrBvm+l/kH4d4HqI/Cajc8spceoAX17Bbq7TKGFN4v6vtgsbVbCba7UJqeN7cbtiBbu5qQH7CQp2c70SVgP2AxTs5oqN/FPbpe31Vw1Ybd9otYLVVitYDdh/WMHGV2zk39ouba+/asBq+07AagWr7TutHiJrqxWsBqyeg/1MwP7Udmm7bgWr43t5wGoF+/PHc6z+O7W+5XjbHxmmHjU3LyFkKWers8ty+wkKdjtqPdKAzLvNh6O+N5Nmlzm/Tx/zvF9G3SlL7I5eKhT80OzOqfdja3Q2wMJh9K6a7f0EorZ6qG1WszyO2I0Rna1UixVzZsBubk+3yVTGo/UyLnVtzdXodSdGelMmz5vH6vLSkjlNR/HRepLfx815z1jf+31x67GKyEOPHTpZNxduibOVaumlnsNeP8HXSAvH46TYczzJRG+kpbe0tO5LWbHjl0fNu3kGwLZ9nllkWVY/zbr30wDbMpXtZ92G563tdwB281m+HrtdVJ/HEg0TgFFnQYeqPJyvNLFVpoacr3nqPRp/FTDOl+WtCJg77P9MwH7DGBlm3Pr53P2nFewBsGq++tQGEOpWuYJNW88Jc04GMLLOU5mKAdX5IIHEeUbfDAMaHwcsq9cmcPDwRcCQr8gNFHP7PxEw4uaOkeDlBJtzlUpYD5wZsPGpgEGcnxvcWuWBnlAiqJePzk+P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 \ No newline at end of file +v0.33.2-beta +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWoAAAAqCAMAAACtKeEJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1N0E5REJCRkFFMDQxMUU5OEY4N0I5QzNCNzMzRDExMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1N0E5REJDMEFFMDQxMUU5OEY4N0I5QzNCNzMzRDExMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU3QTlEQkJEQUUwNDExRTk4Rjg3QjlDM0I3MzNEMTEwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU3QTlEQkJFQUUwNDExRTk4Rjg3QjlDM0I3MzNEMTEwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+nlXGtQAAAwBQTFRFwdXgB1aElMXhRZrKCXKtB2edhLzdioqKgICAstPm4e/37/T3oaGhHHGiY5WxYmJiysrKaWlpBl6RKo3F0dHRFWmabW1tRYCiBW2p0ebyVIuqNXWazs7Onp6eoszlBnCsh7/fxsbGCna0CWSYCFyNPz8/drXZ5+fnCHe3InWlREREBFyOJGqSZqzVBFOAF4C9scrYdKfERZG9RkZGJHmqOpXKCWqhCWGUk7vThISEMJPLI4S8G4XBkZGRubm5ZKvTpaWlqampwMDAtbW1BlWCcnJy2tragoKCrKyseHh4V6TRZWVlRoqxS0tL39/fdbLVQUFB4ODgstXqV5W5BWmikrTIBGCUQkJCFH24lpaWg6rBpM7mCW2lCViFBnKwBVqKtra2BWWbdHR0wsLCNHylhLTRdnZ2SZ7O8PX3vr6+Sp/Pcp64ob/QGG2er6+vsc7eJnGdosbblJSUosnfc6C6ZqjOosDRBnSzBGKY3NzcGGKNCWieR5zNgq7HRYiuBWulicHiQ36gNpLGJm6XWabTocPXg7PPB2ykAnO0AXKzUVFRU1NTVFRUVVVVC3y9UlJSCnu8B3i5BXa3VlZWDoDABHW2A3S0A3W1Dn/ABHa2A3S1EoPDEoPEEoTEE4TFAHKyV1dXDn+/Bne4DX6/DX6+DH2+DH29CHm5CXu7CXq6CXq7Ojo6qqqq1dXVq6ur1NTUPT09PDw8SEhIOzs7SUlJfn5+6urq8Pf7gqnAwt7unZ2dg7zc8/PzTExMf39/9PT04Orwwd7uwNTfwd3t9fX1hKzC0eDojIyMFF6Jhb7ewd3u1tbWhoaG4Orvg6/IdLPY0N/nhL3dw9/vwt/vg6vCB1iHBXS0Y56/C3q56Ojogrvbe3t7VaLPwdvqwtzrss/gaK/XRpvLJYrEwt7vkbTIk7bK0OTwBWefsszcwdfkhKvCgrjXCnm5ZJi2NYq7EYLDEIHCD4DBWVlZWlpaX19fW1tbXFxcXl5eTU1NT09PUFBQWFhYXV1dTk5O////////eFiiEwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAv+SURBVHja7JcJVBRXFoYLRDGIIKgICqJiS2y0JbaixA0Q1DZC0KgJokY0Dk5inKzGRLOZbcZGFpmZTGYLITqoiNCINCIG9y0uwajZJotJjMlktiRMZBl+5r73qrqrugE98RwnleN3jlX33neXen8VVbbU2npwRUC9jhn15x8/nz5jb22VWmcm1euaUX/SA7eGtEoHky7rm1F/1AW32qUVl/Uu9R/0wTNS0n91zqh/6YNbpf/ekPo68ROQ+t86Qfpe79yQ+rox9BudIP1H79yQ+vpJ/WudIH2nd4b+Tie0KbXFd9qKNMv/VUBL7NXOH/paO3zT85MBA+51i45/foAqzJOGjHYrvndAG7Wv3Yszr/1gpG/d8K0Ep3Ja0LfXSNC0tB9Y+SbevMrMoa+3gyffhc9oTbDnGbE5n+e5m+kj3DParHQRtT/v0jITZ9qb9nrmgMzXO8RNav83gchFYWFLaoBp1yp17FULdg1Sb2ybY1h2y4w7PoZ9vDqaCRw+dGjlMiBTJCH60KFouGRR0sVDF/fKSerqtzdubHfesY0dIjW7kABMMHBORE5rvkamouQHVhoNxqvMHLqpTXoC/RYQEtLV4cyVz7HoE3tFeMihJ5jbD/hEnSX14UmHMUvblKTe1B4k9aYOkdzEwQlDanlystlgSA66WmGCpk71V7mWqZYrSj1VydFgURo5pabeLqNcpP5LmwzBlwvme3lF9IFdFd3otWBBYEzM6nOH8DbzYxYsiIiJiaAbckxdTEmrY1YP7gtom2ayqvGZmepQ5mhhHFO1GJ2pyRG4St0DoYY9wmxJTW5u3o7twgPk49QeIAG70r+0meCrR/jLPYFrVIKuacyttHBH0PUIKuX+lThCR/8E/jFgprqT+EpUsp7KXHVvik1lLQ+mqa+4+6Zsznigp7DS4ZmdPQt/G8ScMcDobCdeETz67lg8zM7zY95lp0GH8agqKXuMF096CsjWkInPRn/GXuLH5Jn8pe4znUx5q6wgRFjp47XFUoEWeqgb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 \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/controller/openclash.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/controller/openclash.lua old mode 100755 new mode 100644 index 05112938ac..633bac6b73 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/controller/openclash.lua +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/controller/openclash.lua @@ -7,17 +7,19 @@ function index() entry({"admin", "services", "openclash"},alias("admin", "services", "openclash", "client"), _("OpenClash"), 50).dependent = true - entry({"admin", "services", "openclash", "client"},cbi("openclash/client"),_("Clash Global State"), 20).leaf = true + entry({"admin", "services", "openclash", "client"},form("openclash/client"),_("Overview"), 20).leaf = true entry({"admin", "services", "openclash", "status"},call("action_status")).leaf=true entry({"admin", "services", "openclash", "state"},call("action_state")).leaf=true entry({"admin", "services", "openclash", "startlog"},call("action_start")).leaf=true entry({"admin", "services", "openclash", "currentversion"},call("action_currentversion")) entry({"admin", "services", "openclash", "lastversion"},call("action_lastversion")) - entry({"admin", "services", "openclash", "config"},cbi("openclash/config"),_("Server Config"), 30).leaf = true - entry({"admin", "services", "openclash", "settings"},cbi("openclash/settings"),_("Clash Settings"), 40).leaf = true - entry({"admin", "services", "openclash", "update"},cbi("openclash/update"),_("Update Setting"), 50).leaf = true - entry({"admin", "services", "openclash", "rule"},cbi("openclash/rule"),_("Rules Setting"), 60).leaf = true - entry({"admin", "services", "openclash", "log"},cbi("openclash/log"),_("Logs"), 70).leaf = true + entry({"admin", "services", "openclash", "update"},call("action_update")) + entry({"admin", "services", "openclash", "update_ma"},call("action_update_ma")) + entry({"admin", "services", "openclash", "opupdate"},call("action_opupdate")) + entry({"admin", "services", "openclash", "coreupdate"},call("action_coreupdate")) + entry({"admin", "services", "openclash", "settings"},cbi("openclash/settings"),_("Takeover Settings"), 30).leaf = true + entry({"admin", "services", "openclash", "config"},form("openclash/config"),_("Server Config"), 40).leaf = true + entry({"admin", "services", "openclash", "log"},form("openclash/log"),_("Logs"), 50).leaf = true end @@ -36,31 +38,90 @@ local function is_watchdog() end local function config_check() - return luci.sys.call("grep '^Proxy Group:$' /etc/openclash/config.yml 1>/dev/null && grep '^Rule:$' /etc/openclash/config.yml 1>/dev/null && grep '^- GEOIP' /etc/openclash/config.yml 1>/dev/null && grep ' nameserver:$' /etc/openclash/config.yml 1>/dev/null") == 0 + local yaml = luci.sys.call("ls -l /etc/openclash/config.yaml >/dev/null 2>&1") + local yml = luci.sys.call("ls -l /etc/openclash/config.yml >/dev/null 2>&1") + local nameserver,proxy,group,rule + if (yaml == 0) then + nameserver = luci.sys.call("egrep '^ {0,}nameserver:' /etc/openclash/config.yaml >/dev/null 2>&1") + proxy = luci.sys.call("egrep '^ {0,}Proxy:' /etc/openclash/config.yaml >/dev/null 2>&1") + group = luci.sys.call("egrep '^ {0,}Proxy Group:' /etc/openclash/config.yaml >/dev/null 2>&1") + rule = luci.sys.call("egrep '^ {0,}Rule:' /etc/openclash/config.yaml >/dev/null 2>&1") + else + if (yml == 0) then + nameserver = luci.sys.call("egrep '^ {0,}nameserver:' /etc/openclash/config.yml >/dev/null 2>&1") + proxy = luci.sys.call("egrep '^ {0,}Proxy:' /etc/openclash/config.yml >/dev/null 2>&1") + group = luci.sys.call("egrep '^ {0,}Proxy Group:' /etc/openclash/config.yml >/dev/null 2>&1") + rule = luci.sys.call("egrep '^ {0,}Rule:' /etc/openclash/config.yml >/dev/null 2>&1") + end + end + if (yaml == 0) or (yml == 0) then + if (nameserver == 0) then + nameserver = "" + else + nameserver = " - DNS服务器" + end + if (proxy == 0) then + proxy = "" + else + proxy = " - 代理服务器" + end + if (group == 0) then + group = "" + else + group = " - 策略组" + end + if (rule == 0) then + rule = "" + else + rule = " - 规则" + end + return nameserver..proxy..group..rule + elseif (yaml ~= 0) and (yml ~= 0) then + return "1" + end end local function cn_port() return luci.sys.exec("uci get openclash.config.cn_port 2>/dev/null") end +local function mode() + return luci.sys.exec("uci get openclash.config.en_mode 2>/dev/null") +end + local function config() - return luci.sys.exec("ls -l --full-time /etc/openclash/config.bak|awk '{print $6,$7;}' 2>/dev/null") + local config_update = luci.sys.exec("ls -l --full-time /etc/openclash/config.bak 2>/dev/null |awk '{print $6,$7;}'") + if (config_update ~= "") then + return config_update + else + local yaml = luci.sys.call("ls -l /etc/openclash/config.yaml >/dev/null 2>&1") + if (yaml == 0) then + return "0" + else + local yml = luci.sys.call("ls -l /etc/openclash/config.yml >/dev/null 2>&1") + if (yml == 0) then + return "0" + else + return "1" + end + end + end end local function ipdb() - return luci.sys.exec("ls -l --full-time /etc/openclash/Country.mmdb|awk '{print $6,$7;}' 2>/dev/null") + return luci.sys.exec("ls -l --full-time /etc/openclash/Country.mmdb 2>/dev/null |awk '{print $6,$7;}'") end local function lhie1() - return luci.sys.exec("ls -l --full-time /etc/openclash/lhie1.yml|awk '{print $6,$7;}' 2>/dev/null") + return luci.sys.exec("ls -l --full-time /etc/openclash/lhie1.yaml 2>/dev/null |awk '{print $6,$7;}'") end local function ConnersHua() - return luci.sys.exec("ls -l --full-time /etc/openclash/ConnersHua.yml|awk '{print $6,$7;}' 2>/dev/null") + return luci.sys.exec("ls -l --full-time /etc/openclash/ConnersHua.yaml 2>/dev/null |awk '{print $6,$7;}'") end local function ConnersHua_return() - return luci.sys.exec("ls -l --full-time /etc/openclash/ConnersHua_return.yml|awk '{print $6,$7;}' 2>/dev/null") + return luci.sys.exec("ls -l --full-time /etc/openclash/ConnersHua_return.yaml 2>/dev/null |awk '{print $6,$7;}'") end local function daip() @@ -72,17 +133,73 @@ local function dase() end local function check_lastversion() - return luci.sys.exec("sh /usr/share/openclash/openclash_version.sh && sed -n '/^data:/,$p' /tmp/openclash_last_version 2>/dev/null") + return luci.sys.exec("sh /usr/share/openclash/openclash_version.sh && sed -n '/^https:/,$p' /tmp/openclash_last_version 2>/dev/null") end local function check_currentversion() - return luci.sys.exec("sed -n '/^data:/,$p' /etc/openclash/openclash_version 2>/dev/null") + return luci.sys.exec("sed -n '/^data:image/,$p' /etc/openclash/openclash_version 2>/dev/null") end local function startlog() return luci.sys.exec("sed -n '$p' /tmp/openclash_start.log 2>/dev/null") end +local function coremodel() + return luci.sys.exec("cat /proc/cpuinfo |grep 'cpu model' 2>/dev/null |awk -F ': ' '{print $2}' 2>/dev/null") +end + +local function coremodel2() + return luci.sys.exec("opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' 2>/dev/null") +end + +local function corecv() +if not nixio.fs.access("/etc/openclash/clash") then + return "0" +else + return luci.sys.exec("/etc/openclash/clash -v 2>/dev/null 2>/dev/null |awk -F ' ' '{print $2}'") +end +end + +local function corelv() + return luci.sys.exec("sh /usr/share/openclash/clash_version.sh && sed -n 1p /tmp/clash_last_version 2>/dev/null") +end + +local function opcv() + return luci.sys.exec("sed -n 1p /etc/openclash/openclash_version 2>/dev/null") +end + +local function oplv() + return luci.sys.exec("sh /usr/share/openclash/openclash_version.sh && sed -n 1p /tmp/openclash_last_version 2>/dev/null |sed 's/^v//g' 2>/dev/null") +end + +local function opup() + return luci.sys.exec("uci set openclash.config.update=1 && uci commit openclash && rm -rf /tmp/openclash_last_version 2>/dev/null && sh /usr/share/openclash/openclash_version.sh && sh /usr/share/openclash/openclash_update.sh 2>/dev/null") +end + +local function coreup() + return luci.sys.exec("uci set openclash.config.enable=1 && uci commit openclash && rm -rf /tmp/clash_last_version 2>/dev/null && sh /usr/share/openclash/clash_version.sh && sh /usr/share/openclash/openclash_core.sh 2>/dev/null") +end + +local function corever() + return luci.sys.exec("uci get openclash.config.core_version 2>/dev/null") +end + +local function upchecktime() + local corecheck = luci.sys.exec("ls -l --full-time /tmp/clash_last_version 2>/dev/null |awk '{print $6,$7;}'") + local opcheck + if not corecheck or corecheck == "" then + opcheck = luci.sys.exec("ls -l --full-time /tmp/openclash_last_version 2>/dev/null |awk '{print $6,$7;}'") + if not opcheck or opcheck == "" then + return "1" + else + return opcheck + end + else + return corecheck + end +end + + function action_status() luci.http.prepare_content("application/json") luci.http.write_json({ @@ -91,7 +208,8 @@ function action_status() daip = daip(), dase = dase(), web = is_web(), - cn_port = cn_port(); + cn_port = cn_port(), + mode = mode(); }) end function action_state() @@ -126,3 +244,39 @@ function action_start() startlog = startlog(); }) end + +function action_update() + luci.http.prepare_content("application/json") + luci.http.write_json({ + coremodel = coremodel(), + coremodel2 = coremodel2(), + corecv = corecv(), + corelv = corelv(), + opcv = opcv(), + corever = corever(), + upchecktime = upchecktime(), + oplv = oplv(); + }) +end + +function action_update_ma() + luci.http.prepare_content("application/json") + luci.http.write_json({ + oplv = oplv(), + corever = corever(); + }) +end + +function action_opupdate() + luci.http.prepare_content("application/json") + luci.http.write_json({ + opup = opup(); + }) +end + +function action_coreupdate() + luci.http.prepare_content("application/json") + luci.http.write_json({ + coreup = coreup(); + }) +end \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/client.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/client.lua old mode 100755 new mode 100644 index f8ed6104de..a128244c04 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/client.lua +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/client.lua @@ -4,6 +4,7 @@ local SYS = require "luci.sys" local HTTP = require "luci.http" local DISP = require "luci.dispatcher" local UTIL = require "luci.util" +local uci = require("luci.model.uci").cursor() local t = { {enable, disable} @@ -18,15 +19,18 @@ o = s:option(Button, "enable") o.inputtitle = translate("Enable Clash") o.inputstyle = "apply" o.write = function() - os.execute("uci set openclash.config.enable=1 && uci commit openclash && /etc/init.d/openclash restart >/dev/null 2>&1 &") - HTTP.redirect(DISP.build_url("admin", "services", "openclash")) + uci:set("openclash", "config", "enable", 1) + uci:commit("openclash") + SYS.call("/etc/init.d/openclash restart >/dev/null 2>&1 &") end o = s:option(Button, "disable") o.inputtitle = translate("Disable Clash") o.inputstyle = "reset" o.write = function() - os.execute("uci set openclash.config.enable=0 && uci commit openclash && /etc/init.d/openclash stop >/dev/null 2>&1 &") + uci:set("openclash", "config", "enable", 0) + uci:commit("openclash") + SYS.call("/etc/init.d/openclash stop >/dev/null 2>&1 &") end m = Map("openclash") diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/config.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/config.lua old mode 100755 new mode 100644 index 20fad5b89e..e0f3e87602 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/config.lua +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/config.lua @@ -4,25 +4,23 @@ local SYS = require "luci.sys" local HTTP = require "luci.http" local DISP = require "luci.dispatcher" local UTIL = require "luci.util" - - -local http = luci.http +local fs = require "luci.openclash" +local CHIF = "0" ful = SimpleForm("upload", translate("Server Configuration"), nil) ful.reset = false ful.submit = false -sul =ful:section(SimpleSection, "", translate("")) +sul =ful:section(SimpleSection, "") o = sul:option(FileUpload, "") -o.title = translate("Upload Clash Configuration") -o.template = "openclash/clash_upload" -o.description = translate("NB: Rename your config file to config.yml before upload. file will save to /etc/openclash") +o.template = "openclash/upload" um = sul:option(DummyValue, "", nil) -um.template = "openclash/clash_dvalue" +um.template = "openclash/dvalue" -local dir, fd +local dir, fd, clash +clash = "/etc/openclash/clash" dir = "/etc/openclash/" -http.setfilehandler( +HTTP.setfilehandler( function(meta, chunk, eof) if not fd then if not meta then return end @@ -40,35 +38,120 @@ http.setfilehandler( if eof and fd then fd:close() fd = nil - um.value = translate("File saved to") .. ' "/etc/openclash/' .. meta.file .. '"' - SYS.exec("cp /etc/openclash/config.yml /etc/openclash/config.bak") + if (meta.file == "config.yml") then + SYS.call("cp /etc/openclash/config.yml /etc/openclash/config.bak") + SYS.call("mv /etc/openclash/config.yml /etc/openclash/config.yaml") + elseif (meta.file == "config.yaml") then + SYS.call("cp /etc/openclash/config.yaml /etc/openclash/config.bak") + end + if (meta.file == "clash") then + NXFS.chmod(clash, 755) + end + um.value = translate("File saved to") .. ' "/etc/openclash"' + CHIF = "1" end end ) -if luci.http.formvalue("upload") then - local f = luci.http.formvalue("ulfile") +if HTTP.formvalue("upload") then + local f = HTTP.formvalue("ulfile") if #f <= 0 then um.value = translate("No specify upload file.") end end -m = Map("openclash") -s = m:section(TypedSection, "openclash") -s.anonymous = true -s.addremove=false +m = SimpleForm("openclash") +m.reset = false +m.submit = false +local tab = { + {user, default} +} -local conf = "/etc/openclash/config.yml" -sev = s:option(TextValue, "conf") -sev.readonly=true -sev.description = translate("Changes to config file must be made from source") +s = m:section(Table, tab) + +local conf = "/etc/openclash/config.yaml" +local yconf = "/etc/openclash/config.yml" +local dconf = "/etc/openclash/default.yaml" +local bconf = "/etc/openclash/config.bak" + +sev = s:option(Value, "user") +sev.template = "cbi/tvalue" +sev.description = translate("You Can Modify config file Here, Except The Settings That Were Taken Over") sev.rows = 20 sev.wrap = "off" sev.cfgvalue = function(self, section) - return NXFS.readfile(conf) or "" + return NXFS.readfile(conf) or NXFS.readfile(yconf) or NXFS.readfile(bconf) or NXFS.readfile(dconf) or "" end sev.write = function(self, section, value) +if (CHIF == "0") then + value = value:gsub("\r\n?", "\n") + NXFS.writefile("/etc/openclash/config.yaml", value) +end +end + +def = s:option(Value, "default") +def.template = "cbi/tvalue" +def.description = translate("Default Config File With Correct General-Settings") +def.rows = 20 +def.wrap = "off" +def.readonly = true +def.cfgvalue = function(self, section) + return NXFS.readfile(dconf) or "" +end +def.write = function(self, section, value) +end + + +local t = { + {Commit, Apply, Download} +} + +a = m:section(Table, t) + +o = a:option(Button, "Commit") +o.inputtitle = translate("Commit Configurations") +o.inputstyle = "apply" +o.write = function() + SYS.call("uci commit openclash") +end + +o = a:option(Button, "Apply") +o.inputtitle = translate("Apply Configurations") +o.inputstyle = "apply" +o.write = function() + SYS.call("uci set openclash.config.enable=1 && uci commit openclash && /etc/init.d/openclash restart >/dev/null 2>&1 &") + HTTP.redirect(DISP.build_url("admin", "services", "openclash")) +end + +o = a:option(Button, "Download") +o.inputtitle = translate("Download Configurations") +o.inputstyle = "apply" +o.write = function () + local sPath, sFile, fd, block + sPath = "/etc/openclash/config.yaml" + sFile = NXFS.basename(sPath) + if fs.isdirectory(sPath) then + fd = io.popen('tar -C "%s" -cz .' % {sPath}, "r") + sFile = sFile .. ".tar.gz" + else + fd = nixio.open(sPath, "r") + end + if not fd then + return + end + HTTP.header('Content-Disposition', 'attachment; filename="%s"' % {sFile}) + HTTP.prepare_content("application/octet-stream") + while true do + block = fd:read(nixio.const.buffersize) + if (not block) or (#block ==0) then + break + else + HTTP.write(block) + end + end + fd:close() + HTTP.close() end return ful , m diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/log.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/log.lua old mode 100755 new mode 100644 index 11d09bf203..28d7d6014d --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/log.lua +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/log.lua @@ -22,7 +22,6 @@ log.cfgvalue = function(self, section) return NXFS.readfile(clog) or "" end log.write = function(self, section, value) - NXFS.writefile(clog, value:gsub("\r\n", "\n")) end return m \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/rule.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/rule.lua deleted file mode 100755 index 72f587d529..0000000000 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/rule.lua +++ /dev/null @@ -1,123 +0,0 @@ --- -local NXFS = require "nixio.fs" -local SYS = require "luci.sys" -local HTTP = require "luci.http" -local DISP = require "luci.dispatcher" -local UTIL = require "luci.util" - -m = Map("openclash", translate("Rules Setting")) -s = m:section(TypedSection, "openclash") -s.anonymous = true - -o = s:option(ListValue, "enable_custom_clash_rules", translate("Custom Clash Rules")) -o.description = translate("Use Custom Rules") -o:value("0", translate("Disable Custom Clash Rules")) -o:value("1", translate("Enable Custom Clash Rules")) -o.default = 0 - -o = s:option(ListValue, "rule_source", translate("Enable Other Rules")) -o.description = translate("Use Other Rules") -o:value("0", translate("Disable Other Rules")) -o:value("lhie1", translate("lhie1 Rules")) -o:value("ConnersHua", translate("ConnersHua Rules")) -o:value("ConnersHua_return", translate("ConnersHua Return Rules")) - -os.execute("awk '/Proxy Group:/,/Rule:/{print}' /etc/openclash/config.yml |grep ^- |grep name: |sed 's/,.*//' |awk -F 'name: ' '{print $2}' |sed 's/\"//g' >/tmp/Proxy_Group 2>&1") -os.execute("echo 'DIRECT' >>/tmp/Proxy_Group") -os.execute("echo 'REJECT' >>/tmp/Proxy_Group") -file = io.open("/tmp/Proxy_Group", "r"); - -o = s:option(ListValue, "GlobalTV", translate("GlobalTV")) -o:depends("rule_source", "lhie1") -o:depends("rule_source", "ConnersHua") - for l in file:lines() do - o:value(l) - end - file:seek("set") -o = s:option(ListValue, "AsianTV", translate("AsianTV")) -o:depends("rule_source", "lhie1") -o:depends("rule_source", "ConnersHua") - for l in file:lines() do - o:value(l) - end - file:seek("set") -o = s:option(ListValue, "Proxy", translate("Proxy")) -o:depends("rule_source", "lhie1") -o:depends("rule_source", "ConnersHua") -o:depends("rule_source", "ConnersHua_return") - for l in file:lines() do - o:value(l) - end - file:seek("set") -o = s:option(ListValue, "Apple", translate("Apple")) -o:depends("rule_source", "lhie1") -o:depends("rule_source", "ConnersHua") - for l in file:lines() do - o:value(l) - end - file:seek("set") -o = s:option(ListValue, "AdBlock", translate("AdBlock")) -o:depends("rule_source", "lhie1") -o:depends("rule_source", "ConnersHua") - for l in file:lines() do - o:value(l) - end - file:seek("set") -o = s:option(ListValue, "Domestic", translate("Domestic")) -o:depends("rule_source", "lhie1") -o:depends("rule_source", "ConnersHua") - for l in file:lines() do - o:value(l) - end - file:seek("set") -o = s:option(ListValue, "Others", translate("Others")) -o:depends("rule_source", "lhie1") -o:depends("rule_source", "ConnersHua") -o:depends("rule_source", "ConnersHua_return") -o.description = translate("Choose Proxy Group, Base On Your Servers Group in config.yml") - for l in file:lines() do - o:value(l) - end - file:close() - -custom_rules = s:option(Value, "custom_rules", translate("Custom Clash Rules Here"), translate("For More Go Github:https://github.com/Dreamacro/clash")) -custom_rules.template = "cbi/tvalue" -custom_rules.rows = 20 -custom_rules.wrap = "off" -custom_rules:depends("enable_custom_clash_rules", 1) - -function custom_rules.cfgvalue(self, section) - return NXFS.readfile("/etc/config/openclash_custom_rules.list") or "" -end -function custom_rules.write(self, section, value) - if value then - value = value:gsub("\r\n", "\n") - NXFS.writefile("/etc/config/openclash_custom_rules.list", value) - end -end - -local t = { - {Commit, Apply} -} - -a = SimpleForm("apply") -a.reset = false -a.submit = false -s = a:section(Table, t) - -o = s:option(Button, "Commit") -o.inputtitle = translate("Commit Configurations") -o.inputstyle = "apply" -o.write = function() - os.execute("uci commit openclash") -end - -o = s:option(Button, "Apply") -o.inputtitle = translate("Apply Configurations") -o.inputstyle = "apply" -o.write = function() - os.execute("uci commit openclash && /etc/init.d/openclash restart >/dev/null 2>&1 &") - HTTP.redirect(DISP.build_url("admin", "services", "openclash")) -end - -return m , a diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/settings.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/settings.lua old mode 100755 new mode 100644 index 65d7f3dfd0..a138493042 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/settings.lua +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/settings.lua @@ -4,70 +4,284 @@ local SYS = require "luci.sys" local HTTP = require "luci.http" local DISP = require "luci.dispatcher" local UTIL = require "luci.util" +local uci = require("luci.model.uci").cursor() -local t = { - {Commit, Apply} -} - -a = SimpleForm("apply") -a.reset = false -a.submit = false -s = a:section(Table, t) - -o = s:option(Button, "Commit") -o.inputtitle = translate("Commit Configurations") -o.inputstyle = "apply" -o.write = function() - os.execute("uci commit openclash") -end - -o = s:option(Button, "Apply") -o.inputtitle = translate("Apply Configurations") -o.inputstyle = "apply" -o.write = function() - os.execute("uci commit openclash && /etc/init.d/openclash restart >/dev/null 2>&1 &") - HTTP.redirect(DISP.build_url("admin", "services", "openclash")) -end - -m = Map("openclash", translate("Clash Settings")) +m = Map("openclash", translate("Takeover Settings")) m.pageaction = false - s = m:section(TypedSection, "openclash") +s.title = translate("Will Modify The Config File Or Subscribe According To The Settings On This Page") s.anonymous = true -o = s:option(ListValue, "en_mode", translate("Select Mode")) -o.description = translate("Will to Take Over Your General Settings, Network Error Try Flush DNS Cache") -o:value("0", translate("Disable Mode Control")) +s:tab("settings", translate("General Settings")) +s:tab("rules", translate("Rules Setting")) +s:tab("dashboard", translate("Dashboard Settings")) +s:tab("config_update", translate("Config Update")) +s:tab("rules_update", translate("Rules Update")) +s:tab("geo_update", translate("GEOIP Update")) +s:tab("version_update", translate("Version Update")) + +---- General Settings +o = s:taboption("settings", ListValue, "core_version", translate("Chose to Download")) +o.description = translate("For Core Update, Wrong Version Will Not Work") +o:value("linux-386") +o:value("linux-amd64", translate("linux-amd64(x86-64)")) +o:value("linux-armv5") +o:value("linux-armv6") +o:value("linux-armv7") +o:value("linux-armv8") +o:value("linux-mips-hardfloat") +o:value("linux-mips-softfloat") +o:value("linux-mips64") +o:value("linux-mips64le") +o:value("linux-mipsle") +o:value("0", translate("Not Set")) +o.default=0 + +o = s:taboption("settings", ListValue, "en_mode", translate("Select Mode")) +o.description = translate("Select Mode For OpenClash Work, Network Error Try Flush DNS Cache") o:value("redir-host", translate("redir-host")) o:value("fake-ip", translate("fake-ip")) -o.default = 0 +o.default = "redir-host" -o = s:option(ListValue, "enable_custom_dns", translate("Custom DNS Setting")) +o = s:taboption("settings", ListValue, "enable_custom_dns", translate("Custom DNS Setting")) o.description = translate("Set OpenClash Upstream DNS Resolve Server") -o:value("0", translate("Disable Custom DNS Setting")) -o:value("1", translate("Enable Custom DNS Setting")) +o:value("0", translate("Disable")) +o:value("1", translate("Enable")) o.default = 0 -o = s:option(Value, "proxy_port") -o.title = translate("Clash config redir-port") +o = s:taboption("settings", ListValue, "ipv6_enable", translate("Enable ipv6 Resolve")) +o.description = translate("Force Enable to Resolve ipv6 DNS Requests") +o:value("0", translate("Disable")) +o:value("1", translate("Enable")) +o.default=0 + +o = s:taboption("settings", Value, "proxy_port") +o.title = translate("Redir Port") o.default = 7892 o.datatype = "port" o.rmempty = false -o.description = translate("Clash Redir Port, Please Make Sure Ports Available") +o.description = translate("Please Make Sure Ports Available") -o = s:option(Value, "cn_port") +o = s:taboption("settings", Value, "http_port") +o.title = translate("HTTP(S) Port") +o.default = 7890 +o.datatype = "port" +o.rmempty = false +o.description = translate("Please Make Sure Ports Available") + +o = s:taboption("settings", Value, "socks_port") +o.title = translate("SOCKS5 Port") +o.default = 7891 +o.datatype = "port" +o.rmempty = false +o.description = translate("Please Make Sure Ports Available") + +---- Rules Settings +o = s:taboption("rules", ListValue, "enable_custom_clash_rules", translate("Custom Clash Rules")) +o.description = translate("Use Custom Rules") +o:value("0", translate("Disable")) +o:value("1", translate("Enable")) +o.default = 0 + +o = s:taboption("rules", ListValue, "rule_source", translate("Enable Other Rules")) +o.description = translate("Use Other Rules") +o:value("0", translate("Disable Other Rules")) +o:value("lhie1", translate("lhie1 Rules")) +o:value("ConnersHua", translate("ConnersHua Rules")) +o:value("ConnersHua_return", translate("ConnersHua Return Rules")) + +SYS.call("awk '/Proxy Group:/,/Rule:/{print}' /etc/openclash/config.yaml 2>/dev/null |egrep '^ {0,}-' |grep name: |sed 's/,.*//' |awk -F 'name: ' '{print $2}' |sed 's/\"//g' >/tmp/Proxy_Group 2>&1") +SYS.call("echo 'DIRECT' >>/tmp/Proxy_Group") +SYS.call("echo 'REJECT' >>/tmp/Proxy_Group") +file = io.open("/tmp/Proxy_Group", "r"); + +o = s:taboption("rules", ListValue, "GlobalTV", translate("GlobalTV")) +o:depends("rule_source", "lhie1") +o:depends("rule_source", "ConnersHua") + for l in file:lines() do + o:value(l) + end + file:seek("set") +o = s:taboption("rules", ListValue, "AsianTV", translate("AsianTV")) +o:depends("rule_source", "lhie1") +o:depends("rule_source", "ConnersHua") + for l in file:lines() do + o:value(l) + end + file:seek("set") +o = s:taboption("rules", ListValue, "Proxy", translate("Proxy")) +o:depends("rule_source", "lhie1") +o:depends("rule_source", "ConnersHua") +o:depends("rule_source", "ConnersHua_return") + for l in file:lines() do + o:value(l) + end + file:seek("set") +o = s:taboption("rules", ListValue, "Apple", translate("Apple")) +o:depends("rule_source", "lhie1") +o:depends("rule_source", "ConnersHua") + for l in file:lines() do + o:value(l) + end + file:seek("set") +o = s:taboption("rules", ListValue, "AdBlock", translate("AdBlock")) +o:depends("rule_source", "lhie1") +o:depends("rule_source", "ConnersHua") + for l in file:lines() do + o:value(l) + end + file:seek("set") +o = s:taboption("rules", ListValue, "Domestic", translate("Domestic")) +o:depends("rule_source", "lhie1") +o:depends("rule_source", "ConnersHua") + for l in file:lines() do + o:value(l) + end + file:seek("set") +o = s:taboption("rules", ListValue, "Others", translate("Others")) +o:depends("rule_source", "lhie1") +o:depends("rule_source", "ConnersHua") +o:depends("rule_source", "ConnersHua_return") +o.description = translate("Choose Proxy Group, Base On Your Servers Group in config.yaml") + for l in file:lines() do + o:value(l) + end + file:close() + +---- update Settings +o = s:taboption("config_update", ListValue, "auto_update", translate("Auto Update")) +o.description = translate("Auto Update Server subscription") +o:value("0", translate("Disable")) +o:value("1", translate("Enable")) +o.default=0 + +o = s:taboption("config_update", ListValue, "config_update_week_time", translate("Update Time (Every Week)")) +o:value("*", translate("Every Day")) +o:value("1", translate("Every Monday")) +o:value("2", translate("Every Tuesday")) +o:value("3", translate("Every Wednesday")) +o:value("4", translate("Every Thursday")) +o:value("5", translate("Every Friday")) +o:value("6", translate("Every Saturday")) +o:value("7", translate("Every Sunday")) +o.default=1 + +o = s:taboption("config_update", ListValue, "auto_update_time", translate("Update time (every day)")) +for t = 0,23 do +o:value(t, t..":00") +end +o.default=0 +o.rmempty = false + +o = s:taboption("config_update", ListValue, "config_update_url_type", translate("Update Url Type")) +o:value("clash", translate("Clash")) +o:value("v2ray", translate("V2ray")) +o:value("surge", translate("Surge")) +o.description = translate("Power By fndroid,Use Other Rules If V2ray Subcription") +o.default="clash" + +o = s:taboption("config_update", Value, "subscribe_url") +o.title = translate("Subcription Url") +o.description = translate("Server Subscription Address") +o.rmempty = true + +o = s:taboption("config_update", Button, translate("Config File Update")) +o.title = translate("Update Subcription") +o.inputtitle = translate("Check And Update") +o.inputstyle = "reload" +o.write = function() + uci:set("openclash", "config", "enable", 1) + uci:commit("openclash") + SYS.call("sh /usr/share/openclash/openclash.sh >/dev/null 2>&1 &") + HTTP.redirect(DISP.build_url("admin", "services", "openclash")) +end + +o = s:taboption("rules_update", ListValue, "other_rule_auto_update", translate("Auto Update")) +o.description = translate("Auto Update Other Rules") +o:value("0", translate("Disable")) +o:value("1", translate("Enable")) +o.default=0 + +o = s:taboption("rules_update", ListValue, "other_rule_update_week_time", translate("Update Time (Every Week)")) +o:value("*", translate("Every Day")) +o:value("1", translate("Every Monday")) +o:value("2", translate("Every Tuesday")) +o:value("3", translate("Every Wednesday")) +o:value("4", translate("Every Thursday")) +o:value("5", translate("Every Friday")) +o:value("6", translate("Every Saturday")) +o:value("7", translate("Every Sunday")) +o.default=1 + +o = s:taboption("rules_update", ListValue, "other_rule_update_day_time", translate("Update time (every day)")) +for t = 0,23 do +o:value(t, t..":00") +end +o.default=0 + +o = s:taboption("rules_update", Button, translate("Other Rules Update")) +o.title = translate("Update Other Rules") +o.inputtitle = translate("Check And Update") +o.description = translate("Other Rules Update(Only in Use)") +o.inputstyle = "reload" +o.write = function() + uci:set("openclash", "config", "enable", 1) + uci:commit("openclash") + SYS.call("sh /usr/share/openclash/openclash_rule.sh >/dev/null 2>&1 &") + HTTP.redirect(DISP.build_url("admin", "services", "openclash")) +end + +o = s:taboption("geo_update", ListValue, "geo_auto_update", translate("Auto Update")) +o.description = translate("Auto Update GEOIP Database") +o:value("0", translate("Disable")) +o:value("1", translate("Enable")) +o.default=0 + +o = s:taboption("geo_update", ListValue, "geo_update_week_time", translate("Update Time (Every Week)")) +o:value("*", translate("Every Day")) +o:value("1", translate("Every Monday")) +o:value("2", translate("Every Tuesday")) +o:value("3", translate("Every Wednesday")) +o:value("4", translate("Every Thursday")) +o:value("5", translate("Every Friday")) +o:value("6", translate("Every Saturday")) +o:value("7", translate("Every Sunday")) +o.default=1 + +o = s:taboption("geo_update", ListValue, "geo_update_day_time", translate("Update time (every day)")) +for t = 0,23 do +o:value(t, t..":00") +end +o.default=0 + +o = s:taboption("geo_update", Button, translate("GEOIP Update")) +o.title = translate("Update GEOIP Database") +o.inputtitle = translate("Check And Update") +o.inputstyle = "reload" +o.write = function() + uci:set("openclash", "config", "enable", 1) + uci:commit("openclash") + SYS.call("sh /usr/share/openclash/openclash_ipdb.sh >/dev/null 2>&1 &") + HTTP.redirect(DISP.build_url("admin", "services", "openclash")) +end + +---- Dashboard Settings +o = s:taboption("dashboard", Value, "cn_port") o.title = translate("Dashboard Port") o.default = 9090 o.datatype = "port" o.rmempty = false -o.description = translate("Dashboard hostname is Your Router IP. Dashboard:192.168.1.1/openclash") +o.description = translate("Dashboard Address Example: 192.168.1.1/openclash、192.168.1.1:9090/ui") -o = s:option(Value, "dashboard_password") +o = s:taboption("dashboard", Value, "dashboard_password") o.title = translate("Dashboard Secret") -o.default = 123456 -o.rmempty = false +o.rmempty = true o.description = translate("Set Dashboard Secret") +---- version update +core_update = s:taboption("version_update", DummyValue, "", nil) +core_update.template = "openclash/update" + -- [[ Edit Server ]] -- s = m:section(TypedSection, "dns_servers", translate("Add Custom DNS Servers")) s.anonymous = true @@ -76,32 +290,132 @@ s.sortable = false s.template = "cbi/tblsection" s.rmempty = false +---- enable flag +o = s:option(Flag, "enabled", translate("Enable"), translate("(Enable or Disable)")) +o.rmempty = false +o.default = o.enabled +o.cfgvalue = function(...) + return Flag.cfgvalue(...) or "1" +end + ---- group o = s:option(ListValue, "group", translate("DNS Server Group")) -o:value("nameserver", translate("Nameserver")) -o:value("fallback", translate("Fallback")) -o.default = "udp" +o.description = translate("(NameServer Group Must Be Set)") +o:value("nameserver", translate("NameServer")) +o:value("fallback", translate("FallBack")) +o.default = "nameserver" o.rempty = false ---- IP address -o = s:option(Value, "ip", translate("DNS Server IP")) +o = s:option(Value, "ip", translate("DNS Server Address")) +o.description = translate("(Do Not Add Type Ahead)") +o.placeholder = translate("Not Null") o.datatype = "or(host, string)" -o.rmempty = false +o.rmempty = true ---- port o = s:option(Value, "port", translate("DNS Server Port")) -o.placeholder = "53" +o.description = translate("(Require When Use Non-Standard Port)") o.datatype = "port" -o.rempty = false +o.rempty = true ---- type o = s:option(ListValue, "type", translate("DNS Server Type")) -o:value("udp", translate("udp")) -o:value("tcp", translate("tcp")) -o:value("tls", translate("tls")) +o.description = translate("(Communication protocol)") +o:value("udp", translate("UDP")) +o:value("tcp", translate("TCP")) +o:value("tls", translate("TLS")) +o:value("https", translate("HTTPS")) o.default = "udp" o.rempty = false -return m, a +-- [[ Edit Authentication ]] -- +s = m:section(TypedSection, "authentication", translate("Set Authentication of SOCKS5/HTTP(S)")) +s.anonymous = true +s.addremove = true +s.sortable = false +s.template = "cbi/tblsection" +s.rmempty = false + +---- enable flag +o = s:option(Flag, "enabled", translate("Enable")) +o.rmempty = false +o.default = o.enabled +o.cfgvalue = function(...) + return Flag.cfgvalue(...) or "1" +end + +---- username +o = s:option(Value, "username", translate("Username")) +o.placeholder = translate("Not Null") +o.rempty = true + +---- password +o = s:option(Value, "password", translate("Password")) +o.placeholder = translate("Not Null") +o.rmempty = true + +s = m:section(TypedSection, "openclash", translate("Set Custom Rules, Will Add When Flag Turn on")) +s.anonymous = true + +custom_rules = s:option(Value, "custom_rules") +custom_rules.template = "cbi/tvalue" +custom_rules.description = translate("Custom Rules Here, For More Go Github:https://github.com/Dreamacro/clash/blob/master/README.md") +custom_rules.rows = 20 +custom_rules.wrap = "off" + +function custom_rules.cfgvalue(self, section) + return NXFS.readfile("/etc/config/openclash_custom_rules.list") or "" +end +function custom_rules.write(self, section, value) + + if value then + value = value:gsub("\r\n?", "\n") + NXFS.writefile("/etc/config/openclash_custom_rules.list", value) + end +end + +s = m:section(TypedSection, "openclash", translate("Set Custom Hosts, Only Work with Redir-Host Mode")) +s.anonymous = true + +custom_hosts = s:option(Value, "custom_hosts") +custom_hosts.template = "cbi/tvalue" +custom_hosts.description = translate("Custom Hosts Here, For More Go Github:https://github.com/Dreamacro/clash/blob/master/README.md") +custom_hosts.rows = 20 +custom_hosts.wrap = "off" + +function custom_hosts.cfgvalue(self, section) + return NXFS.readfile("/etc/config/openclash_custom_hosts.list") or "" +end +function custom_hosts.write(self, section, value) + if value then + value = value:gsub("\r\n?", "\n") + NXFS.writefile("/etc/config/openclash_custom_hosts.list", value) + end +end + +local t = { + {Commit, Apply} +} + +a = m:section(Table, t) + +o = a:option(Button, "Commit") +o.inputtitle = translate("Commit Configurations") +o.inputstyle = "apply" +o.write = function() + uci:commit("openclash") +end + +o = a:option(Button, "Apply") +o.inputtitle = translate("Apply Configurations") +o.inputstyle = "apply" +o.write = function() + uci:set("openclash", "config", "enable", 1) + uci:commit("openclash") + SYS.call("/etc/init.d/openclash restart >/dev/null 2>&1 &") + HTTP.redirect(DISP.build_url("admin", "services", "openclash")) +end +return m diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/update.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/update.lua deleted file mode 100755 index cb705276cd..0000000000 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/model/cbi/openclash/update.lua +++ /dev/null @@ -1,97 +0,0 @@ --- -local NXFS = require "nixio.fs" -local SYS = require "luci.sys" -local HTTP = require "luci.http" -local DISP = require "luci.dispatcher" -local UTIL = require "luci.util" - -m = Map("openclash", translate("Update Setting")) -s = m:section(TypedSection, "openclash", translate("Subscription Update")) -s.anonymous = true - -o = s:option(Flag, "auto_update", translate("Auto Update")) -o.description = translate("Auto Update Server subscription") -o.default=0 -o.rmempty = false - -o = s:option(ListValue, "auto_update_time", translate("Update time (every day)")) -for t = 0,23 do -o:value(t, t..":00") -end -o.default=0 -o.rmempty = false - -o = s:option(Value, "subscribe_url") -o.title = translate("Subcription Url") -o.description = translate("Server Subscription Address") -o.rmempty = true - -o = s:option(Button,translate("Config File Update")) -o.title = translate("Update Subcription") -o.inputtitle = translate("Update Configuration") -o.inputstyle = "reload" -o.write = function() - SYS.call("uci commit openclash && sh /usr/share/openclash/openclash.sh >/dev/null 2>&1 &") - HTTP.redirect(DISP.build_url("admin", "services", "openclash")) -end - -f = m:section(TypedSection, "openclash", translate("Other Rules Update(Only in Use)")) -f.anonymous = true -o = f:option(Flag, "other_rule_auto_update", translate("Auto Update")) -o.description = translate("Auto Update Other Rules") -o.default=0 -o.rmempty = false - -o = f:option(ListValue, "other_rule_update_week_time", translate("Update Time (Every Week)")) -o:value("1", translate("Every Monday")) -o:value("2", translate("Every Tuesday")) -o:value("3", translate("Every Wednesday")) -o:value("4", translate("Every Thursday")) -o:value("5", translate("Every Friday")) -o:value("6", translate("Every Saturday")) -o:value("7", translate("Every Sunday")) -o.default=1 - -o = f:option(ListValue, "other_rule_update_day_time", translate("Update time (every day)")) -for t = 0,23 do -o:value(t, t..":00") -end -o.default=0 - -o = f:option(Button,translate("Other Rules Update")) -o.title = translate("Update Other Rules") -o.inputtitle = translate("Start Update Other Rules") -o.inputstyle = "reload" -o.write = function() - SYS.call("uci commit openclash && sh /usr/share/openclash/openclash_rule.sh >/dev/null 2>&1 &") - HTTP.redirect(DISP.build_url("admin", "services", "openclash")) -end - -u = m:section(TypedSection, "openclash", translate("GEOIP(By MaxMind) Update")) -u.anonymous = true -o = u:option(Button,translate("GEOIP Database Update")) -o.title = translate("Update GEOIP Database") -o.inputtitle = translate("Start Update GEOIP Database") -o.inputstyle = "reload" -o.write = function() - SYS.call("sh /usr/share/openclash/openclash_ipdb.sh >/dev/null 2>&1 &") - HTTP.redirect(DISP.build_url("admin", "services", "openclash")) -end - -local t = { - {Commit} -} - -a = SimpleForm("apply") -a.reset = false -a.submit = false -s = a:section(Table, t) - -o = s:option(Button, "Commit") -o.inputtitle = translate("Commit Configurations") -o.inputstyle = "apply" -o.write = function() - os.execute("uci commit openclash") -end - -return m , a diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/openclash.lua b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/openclash.lua new file mode 100644 index 0000000000..0ac22a5aca --- /dev/null +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/openclash.lua @@ -0,0 +1,40 @@ +--[[ +LuCI - Filesystem tools + +Description: +A module offering often needed filesystem manipulation functions + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local fs = require "nixio.fs" + +local type = type + +--- LuCI filesystem library. +module "luci.openclash" + +--- Checks wheather the given path exists and points to a directory. +-- @param dirname String containing the path of the directory to test +-- @return Boolean indicating wheather given path points to directory +function isdirectory(dirname) + return fs.stat(dirname, "type") == "dir" +end + diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/clash_dvalue.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/clash_dvalue.htm deleted file mode 100755 index 73a617d846..0000000000 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/clash_dvalue.htm +++ /dev/null @@ -1,8 +0,0 @@ -<%+cbi/valueheader%> - -<% - local val = self:cfgvalue(section) or self.default or "" - write(pcdata(val)) -%> - -<%+cbi/valuefooter%> diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/clash_upload.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/clash_upload.htm deleted file mode 100755 index 6466ee14d6..0000000000 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/clash_upload.htm +++ /dev/null @@ -1,5 +0,0 @@ -<%+cbi/valueheader%> - - - -<%+cbi/valuefooter%> diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/developer.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/developer.htm old mode 100755 new mode 100644 index cd044db96d..36aa87f248 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/developer.htm +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/developer.htm @@ -1,8 +1,8 @@
- - - + + +
Clash 主程序发布: <%:Collecting data...%> OpenClash 客户端发布: <%:Collecting data...%>
Clash 主程序开发: Dreamacro <%:Collecting data...%> OpenClash 客户端开发: vernesong <%:Collecting data...%>
Clash 客户端开发: frainzy1477 <%:Collecting data...%> MyIP: SukkaW <%:Collecting data...%>
Clash 核心发布: <%:Collecting data...%> OpenClash 客户端发布: <%:Collecting data...%>
Clash 核心开发: Dreamacro <%:Collecting data...%> OpenClash 客户端开发: vernesong <%:Collecting data...%>
Luci For Clash: frainzy1477 <%:Collecting data...%> MyIP: SukkaW <%:Collecting data...%>
@@ -13,14 +13,13 @@ var SukkaW = document.getElementById('_SukkaW'); var binupdate = document.getElementById('_binupdate'); var openupdate = document.getElementById('_openupdate'); - var github = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAMAAACKeiw+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRjUyRDgzQjhBRDcxMUU5ODM5RkRFNTEzOTgzREM4RiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRjUyRDgzQzhBRDcxMUU5ODM5RkRFNTEzOTgzREM4RiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZGNTJEODM5OEFENzExRTk4MzlGREU1MTM5ODNEQzhGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZGNTJEODNBOEFENzExRTk4MzlGREU1MTM5ODNEQzhGIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+F8FkZAAAAddQTFRF////AAAAAQEBAgICcnJyAwMDVVBLZmZma2trFxcXDQ0NCwsLjY2NuLi4UFBQurq6e3t7NjY2PDw8m5ubSEhISkpKMDAw7OTe/vv5cXFxqKiovLy819fX1MvEtbW1hX56UEtG5t/YhX54/f39WVlZmpqaLyso4drU1s7HXFxcVVFNf39/WVJM0dLSoKCgk5OTfHx8ysrKLi4uvb29RkZG6+vrp52Vr6+v1MzGpZuU5d7Z8uvkvrSr8Orkw8PD1cvCWFNNqaKdx720PDczxLqxw7qzQUFBV1dXQDs3qZ+W8fHx0Ma9t62ksbGxubq7IiIhCAgInp6eDg4O5t7Xsami7u7u/fv5oaGhcHBwISIjbGxsJiYnqamp0snA/Pz8o6Oj8PDw1tbWwbivz8/PBwcHUE1L//38g3pzOzs7wcHBSEVFZWVlq6ur29LLn5+fpJuSfHZyIB8f5OTkyMjIYGBgJCIfPj4+ubCoMCwpPDg0FBQUtKqhQEBATEpH6ubi4tnRDg8Qs7Oz1s3F8uvm6enpHhsZvrSsVFBMioN8JiYmsaql+vby/fr3IiIiKioqZ2Bb9/PvhH13HhwaVlRR6eDZPz8/MzMzDQ0OEQ8OOzg0kImCnZSL////7wd0TgAAAJ10Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AMv8vEwAAAF8SURBVHjabNNlY4MwEAbgO2jn1rm7u7u7u7u7u7u7a3/scmSsDHYfmuR9gKbNAcbf2r30e+rqGJkvyDRlIE98yvG31ktUfFSEf+qxScmDqKkME6fiPzUmczZbiIKSBJF9fHF+ZlO9V42rgAIrdp1w0TdkycI84tENNisFAN8X3fRSwkHUeCxb2LHw/YpxIT0tAlTlQGkFY3+aJKp5m9KTawiQ9rKq5jIpDodmGkRvNbdsUn4ODzS4gKY6KT+DSRo8tBxHf8QCvBE7aLmB2Ar2iS20bMN5h9hZyxaU10EgDY0pag26oTwS1qQfGK9mJ+mIPsFNYrH7r06IUjwDxmjE9lcUlo9NWKnjutIKxh7EWTBHHDaY95P16gzWP8deTeedj2gDjmyVzO+dkpsi1J04i331IthZ3uZyTpMbZ483UxVisGJbST+6JbdiMaKjk23IAGd7rnOmRj6ktd5TyafK1+DejLVnG2dbhh85qpco7M66lnNMvVm6nH4LMAB50ohVhJZ1iwAAAABJRU5ErkJggg==" - var release = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAeCAMAAAAfOR5kAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpDNTk0NDQzNThBRDgxMUU5OTgwMkVGQkFDRDdENTg1MyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpDNTk0NDQzNjhBRDgxMUU5OTgwMkVGQkFDRDdENTg1MyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkM1OTQ0NDMzOEFEODExRTk5ODAyRUZCQUNEN0Q1ODUzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkM1OTQ0NDM0OEFEODExRTk5ODAyRUZCQUNEN0Q1ODUzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+JpJc6gAAAPZQTFRFAAAA////+Pj4/v7+/f39+/v7AQEB39/f/Pz88vLyKysr3d3dCgoKpqam6urq4eHh7e3t4+Pj5eXlycnJ9PT09fX1BQUF9/f3AgICy8vLDg4OYmJi2NjY2tra8PDwz8/PNDQ0Pz8/v7+/ra2tu7u7wcHBQkJCjo6Om5ubXFxcXV1dDAwMCQkJLS0trKyszMzMIyMjRUVF0tLSxMTEeXl5ZWVlJiYm+vr61NTUjY2NyMjIXl5ekZGR6OjoV1dXoqKiLi4uRkZGT09P7OzsdnZ2fn5+xsbGsbGx1tbW5+fnFhYW3t7e8fHxY2NjkJCQJSUlERER////3OeyVgAAAFJ0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////AK0tDHEAAAD0SURBVHjajNHXUsMwEAXQKxfshFSSEDoEEnrvvYeS0O7//wyWZEaOpQf2YUd7ZrRaSWBwtesxE+3ybEywAGDdC57mL1/mKmHrKym9hN8g40dlbKv8kfAhrKgk3LR0zE975/iGEEt2k5KPRTjiFRsuXkXRxfu4d/E3nl18i7qLp8ETWzsCDAYWy6fi2cEo7rQomeJuxuDkdUDNZNzY1Pi4HCpA+icLmt/T8o8nNI//jwtTimuGw71qdXhUUmN0o6je8BSLsvoSmdSWCz9t0sveZsX0joyeZ49snmrcqo1OEj9ILbZzA1L0gU+feSbXjs36V4ABANF7Sn61vZbYAAAAAElFTkSuQmCC" - Dreamacro.innerHTML = 'Dreamacro'; - vernesong.innerHTML = 'vernesong'; - frainzy1477.innerHTML = 'frainzy1477'; - SukkaW.innerHTML = 'SukkaW'; - binupdate.innerHTML = 'binupdate'; - openupdate.innerHTML = 'openupdate'; + var github = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABiCAMAAACRZYZ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3FpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo1Y2NjZGI4My1kMGJiLWExNDUtYmYyNy03ZmRkMTJmY2EwYTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RENEOUYxRjE5RjJDMTFFOUEwNjVGMTc0MUI4MUNFQzgiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RENEOUYxRjA5RjJDMTFFOUEwNjVGMTc0MUI4MUNFQzgiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjVjY2NkYjgzLWQwYmItYTE0NS1iZjI3LTdmZGQxMmZjYTBhNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1Y2NjZGI4My1kMGJiLWExNDUtYmYyNy03ZmRkMTJmY2EwYTQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4s6CIvAAACdlBMVEX+/v78/PzExMT9/f35+fn19fX4+Pj6+vrX19fy8vL7+/sICAjr6+vq6urd3d3x8fFDQ0Obm5vw8PDc3Nz29vYoKCi5ubnn5+cPDw/h4eHY2NiOjo6Dg4NLS0vs7OxFRUXv7+/t7e3u7u4vLy8JCQkQEBANDQ0DAwMGBgYEBARpaWnBwcGvr6/39/fQ0NDNzc3IyMh8fHy7u7uEhISjo6MrKytgYGCGhoZ6enqZmZnS0tI0NDShoaGxsbFlZWUgICAWFhYlJSVMTEwsLCwKCgo6OjqUlJQcHBwaGhr09PQpKSldXV2fn5+4uLiQkJACAgLo6Ojp6elGRkba2tqWlpYBAQHZ2dmnp6fFxcWSkpKurq5KSkqysrI9PT0FBQWYmJhnZ2e9vb1zc3NERETz8/N4eHh+fn5mZmbHx8eIiIiKioq1tbVhYWGoqKhXV1cTExMeHh6srKxqamqLi4ukpKTb29sqKirCwsKmpqbOzs5aWlo8PDyMjIzV1dWdnZ2zs7OFhYXl5eUXFxd0dHQHBweenp7W1tZ9fX0iIiLg4OAtLS2NjY3AwMCgoKCJiYmwsLCPj4/U1NRWVlYRERFPT0+Hh4dsbGxvb2/Pz8/Dw8MdHR0uLi5NTU2+vr4fHx/R0dE5OTm/v7+ioqJQUFDGxsbJyckUFBTKyso2NjZRUVEZGRmtra3i4uImJiZSUlLe3t6CgoJUVFRtbW3Ly8sYGBjMzMwwMDDT09NJSUkkJCRISEi2trZkZGRBQUEMDAy6uro/Pz9/f39ra2sODg4nJycSEhJ7e3s7OzsVFRVycnIyMjJcXFxbW1t2dnYbGxv///8AAAD///9H5/bkAAAA0nRSTlP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wD8iKrvAAAFUElEQVR42qya90PbOBTHZRKTQQgBMgoByipll00H0E1bRhfr2l6v+7r3uLbXvXvd19t777333svqf3SpTRzbT4ptyd/fkJ7ex9iK9PSe0B2L8lxeVx//qKO4PdJ3qHhXbXzlloOi1bHIilFJxs2X92CgT1adimY7Awnc2JyFqare0RbjhbhfWVuDTTT54RaRAyKunI0taVZbOSNk44k/sGVV7y9jgKDBSdiW7tsp2IWMhrBtffaxLYjnCmbS1LB1yOm5mFFnCq1C7sUcyrUEQfdjLvX4zSHuVZhTh3LMIA2/YG5VlaWHlE/ATuhyOognCzujHDpE+NIhBv6ugQaR5mPHdMZFgWzCDupNMmQQO6pcEiSgt/nzrM2XF9r0r74hCCFot87iSUmS3Ld2WSXU3nInBjTpG/0AslVvIEiyShdbQUxbpFgL+uYdRshSff8bUlKebjPEmEc1Xq7vmW6ALNB3D0gpuZuVtpn/nHq7zhsMBt8vzOgu6uhTWvtFjWm9YU9GOsjXhqfLl7QqmPve4OkGJOmVGVvXE5mua1pmcNOrhbiMcY9PYlKm8VW6NZBc0MkG8Rv9XExBwAPgTDaIABz5VMhh7NB/AiEfJCGuSvgADn0T5avchUyBXV42yFLoqXscMgd2tbJB2qCnhxSISPoZCywMRPKULUNIYVYNG2QhwdViGfIgocfP9rpcBFcLpATER+gYkhgVIDiLJSCvw+ZnJGath962JyDXsVO/d8oLW5uAwE9yVuLQMeBuD0JhGM8FeCBhwiRG+aBtgsQleJadgurgcYkPcgI4vIHGIJgPEgQOr6Mf4Svkg5QCh/3oqFPLPH25D6HVoC3MBxEmGx0+jS45tSuqEPCb+A/NchriP2d0uBvB89siTsgSo8OfURU8ijn94avQJKencA5cQgib2Tt8kGyYDUMR0HaVD3IcOJyJJoK2Ij7INeBwBtoH2tr5IMXAYTEiHKU8PAzXCPD3GDoJIYU8EEIQuQYdgY0dPBBCIiuKYk6Fj/TIy4tchKivix1yDyHNKqI7RwlsxAyphs7mJ0KilwiQ86yMBwjOWhOQUVIozrgS+0m+mhIQoYrQsYTthf1KchW+G9VvJuF/YKCgOSRPG+Sjw6fEZMYM2/NYWE10FJUhrnnknEmJPUYJJX+ZqZwZt9KSPzYWMc80WpJq/GCqyYh89XeF1qLF4onL0zJCyyHlJ5MF6p6yLDFA1KV6egOmMwAFhul5qtlqRuLzZNP38ihxg9bsdq83jzoJBN+Fm2mLOXUqRFJLGQPKczcbTOctf6QREi5MDFWaJNwSp1I1S5Q6pLxWKo//0Gid5SKsuOYFqVe1STXNTi9T0IiVsNJlxuiTtJA8TY/8zIYD2EXyJxkwgRToc5CtqZ5v5fH9OusyMkRMz/jGkOjUxsTKHv+XtihKm8dPpS2luox54QLNR1amf48mPKNN4X3pIEdgGn0byHYNfaH8+fuBBhokNw3jcUKuXmpXuyvU4Lnx6vFYuvxElM54SyJVHdwpgzyr62IGHeIj109Sn+USR3BiSKGDclMqcfAT73+yl14425naGEUuyLF0JcB4yu5aHjvkt/TFzBXaROj6w1u83iHvs80v2oN0mpVlD5BGFdmCPGpeYI7aiShJkJNWSuWF52ClzQbkCWv1+DwQpK2xDAmVWL6+0GUYOmwVEkc2LmIE9SWwFdYgFQft3fZAe7UxwhVLkHrB9uWYnHiN+RTWnEc6y5iu+WwcTkbJtTTI9nGDyv0FzBeWysdekH2M0iBKor+iq5zr6hVq7Iw8t42+eDW9G5n6vGDi5H8BBgCTacDsFxo/3wAAAABJRU5ErkJggg==" + Dreamacro.innerHTML = 'Dreamacro'; + vernesong.innerHTML = 'vernesong'; + frainzy1477.innerHTML = 'frainzy1477'; + SukkaW.innerHTML = 'SukkaW'; + binupdate.innerHTML = 'binupdate'; + openupdate.innerHTML = 'openupdate'; function Dreamacro_rediret() { @@ -52,5 +51,11 @@ url6='https://github.com/vernesong/OpenClash/releases'; window.open(url6); } + + function imgerrorfun(){ + var img=event.srcElement; + img.src=github; + img.onerror=null; + } //]]> \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/dvalue.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/dvalue.htm new file mode 100644 index 0000000000..4a437e2b9f --- /dev/null +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/dvalue.htm @@ -0,0 +1,13 @@ +<%+cbi/valueheader%> +
+
+<%:Rename your config file to config.yaml before upload what would be save to /etc/openclash%> +
+
+<% + local val = self:cfgvalue(section) or self.default or "" + write(pcdata(val)) +%> +
+
+<%+cbi/valuefooter%> diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/myip.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/myip.htm old mode 100755 new mode 100644 index 6dcfc988b4..c32d5b8b63 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/myip.htm +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/myip.htm @@ -1,28 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + + IP 地址查询 + +
- -
- - +
+ +
+
+

IP 地址

+

+ IP 登录设备: +

+

+ IPIP    国内: +

+

+ 淘宝    国内: +

+

+ IP.SB  海外: +

+

+ IPIFY  海外: +

+
+
+

网站访问检查

+

+ 百度搜索: +

+

+ 网易云音乐: +

+

+ GitHub: +

+

+ Facebook: +

+

+ YouTube: +

+
+
+
+

Powered by ip.skk.moe

+
+
+ \ No newline at end of file + img.onload = () => { + clearTimeout(timeout); + $$.getElementById(cbElID).innerHTML = '连接正常' + } + + img.src = `https://${domain}/favicon.ico?${+(new Date)}` + }, + runcheck: () => { + HTTP.checker('www.baidu.com', 'http-baidu'); + HTTP.checker('s1.music.126.net/style', 'http-163'); + HTTP.checker('github.com', 'http-github'); + HTTP.checker('www.facebook.com', 'http-facebook'); + HTTP.checker('www.youtube.com', 'http-youtube'); + } + }; + + HTTP.runcheck(); + IP.getIpipnetIP(); + IP.getIpifyIP(); + IP.getWebrtcIP(); + + window.onload=myip_Load(); + + function myip_Load() + { + var tbip = document.getElementsByTagName('HEAD').item(0); + var tbipScript= document.createElement("script"); + tbipScript.async = "async"; + tbipScript.src='https://www.taobao.com/help/getip.php'; + tbip.appendChild( tbipScript); + + var sbip = document.getElementsByTagName('HEAD').item(0); + var sbipScript= document.createElement("script"); + sbipScript.async = "async"; + sbipScript.src='https://ipv4.ip.sb/addrinfo?callback=IP.getIpsbIP'; + sbip.appendChild( sbipScript); + + const $$ = document; + random = parseInt(Math.random() * 100000000); + window.ipCallback = (data) => IP.getTaobaoIP(data); + HTTP.runcheck(); + IP.getIpipnetIP(); + IP.getIpifyIP(); + IP.getWebrtcIP(); + setTimeout("myip_Load()",1000*8); + } + + + + + + + diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/state.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/state.htm old mode 100755 new mode 100644 index c07860eaa2..b185601aca --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/state.htm +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/state.htm @@ -1,9 +1,9 @@
- - - + + +
一些必要的状态显示,运行前请确保各项目显示正常,需要更新请到更新设置页面操作
OpenClash 配置文件状态 <%:Collecting data...%> OpenClash 配置文件更新日期 <%:Collecting data...%>
GEOIP(By MaxMind) 数据库日期 <%:Collecting data...%> lhie1 规则更新日期 <%:Collecting data...%>
一些必要的状态显示,运行前请确保各项目显示正常,需要更新请到接管设置页面操作
启动参数检查(配置文件) <%:Collecting data...%> 配置文件更新日期 <%:Collecting data...%>
GEOIP(By MaxMind)数据库日期 <%:Collecting data...%> lhie1 规则更新日期 <%:Collecting data...%>
ConnersHua 规则更新日期 <%:Collecting data...%> ConnersHua 回国规则更新日期 <%:Collecting data...%>
@@ -15,10 +15,52 @@ var ConnersHua = document.getElementById('_ConnersHua'); var ConnersHua_return = document.getElementById('_ConnersHua_return'); var config_check = document.getElementById('_config_check'); - XHR.poll(2, '<%=luci.dispatcher.build_url("admin", "services", "openclash", "state")%>', null, function(x, status) { + XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "state")%>', null, function(x, status) { if ( x && x.status == 200 ) { - config_check.innerHTML = status.config_check ? '<%:Config Normal%>' : '<%:Config Abnormal%>'; - config.innerHTML = status.config ? ""+status.config+"" : ""+"<%:File No Update%>"+""; + if (status.config_check == "") { + config_check.innerHTML = '<%:Config Normal%>'; + } + else if (status.config_check == "1") { + config_check.innerHTML = '<%:未找到配置文件%>'; + } + else { + config_check.innerHTML = ''+status.config_check+'<%: - 参数异常%>'; + } + if (status.config == "1") { + config.innerHTML = "<%:未找到配置文件%>"; + } + else if (status.config == "0") { + config.innerHTML = "<%:原始配置文件%>"; + } + else { + config.innerHTML = ""+status.config+""; + } + ipdb.innerHTML = status.ipdb ? ""+status.ipdb+"" : ""+"<%:File Not Exist%>"+""; + lhie1.innerHTML = status.lhie1 ? ""+status.lhie1+"" : ""+"<%:File Not Exist%>"+""; + ConnersHua.innerHTML = status.ConnersHua ? ""+status.ConnersHua+"" : ""+"<%:File Not Exist%>"+""; + ConnersHua_return.innerHTML = status.ConnersHua_return ? ""+status.ConnersHua_return+"" : ""+"<%:File Not Exist%>"+""; + } + }); + XHR.poll(10, '<%=luci.dispatcher.build_url("admin", "services", "openclash", "state")%>', null, function(x, status) { + if ( x && x.status == 200 ) { + if (status.config_check == "") { + config_check.innerHTML = '<%:Config Normal%>'; + } + else if (status.config_check == "1") { + config_check.innerHTML = '<%:未找到配置文件%>'; + } + else { + config_check.innerHTML = ''+status.config_check+'<%: - 参数异常%>'; + } + if (status.config == "1") { + config.innerHTML = "<%:未找到配置文件%>"; + } + else if (status.config == "0") { + config.innerHTML = "<%:原始配置文件%>"; + } + else { + config.innerHTML = ""+status.config+""; + } ipdb.innerHTML = status.ipdb ? ""+status.ipdb+"" : ""+"<%:File Not Exist%>"+""; lhie1.innerHTML = status.lhie1 ? ""+status.lhie1+"" : ""+"<%:File Not Exist%>"+""; ConnersHua.innerHTML = status.ConnersHua ? ""+status.ConnersHua+"" : ""+"<%:File Not Exist%>"+""; diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/status.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/status.htm old mode 100755 new mode 100644 index 5f87774979..b21bb8bc05 --- a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/status.htm +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/status.htm @@ -1,30 +1,60 @@
- -
- + + - - - - + + + + +
<%:Collecting data...%>
OpenClash 成功启动后请耐心等待运行,然后刷新下方网站访问检查等待连接正常后再使用
OpenClash 主程序 <%:Collecting data...%> OpenClash 守护程序 <%:Collecting data...%>
控制面板登录IP <%:Collecting data...%> 控制面板登录密码 <%:Collecting data...%>
Yacd 控制面板 <%:Collecting data...%> Dashboard 控制面板 <%:Collecting data...%>
Tip: OpenClash 成功启动后请耐心等待下方网站访问检查连接正常后再使用
OpenClash 主程序 <%:Collecting data...%> 控制面板登录IP <%:Collecting data...%>
OpenClash 守护程序 <%:Collecting data...%> 控制面板登录端口 <%:Collecting data...%>
OpenClash 运行模式 <%:Collecting data...%> 控制面板登录密钥 <%:Collecting data...%>
Yacd 控制面板 <%:Collecting data...%> Dashboard 控制面板 <%:Collecting data...%>
+ \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/upload.htm b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/upload.htm new file mode 100644 index 0000000000..3401bd9833 --- /dev/null +++ b/package/cnsztl/luci-app-openclash/files/usr/lib/lua/luci/view/openclash/upload.htm @@ -0,0 +1,7 @@ +<%+cbi/valueheader%> +
+
+<%+cbi/valuefooter%> diff --git a/package/cnsztl/luci-app-openclash/files/usr/share/openclash/clash_version.sh b/package/cnsztl/luci-app-openclash/files/usr/share/openclash/clash_version.sh new file mode 100755 index 0000000000..3444e34f23 --- /dev/null +++ b/package/cnsztl/luci-app-openclash/files/usr/share/openclash/clash_version.sh @@ -0,0 +1,12 @@ +#!/bin/sh +CKTIME=$(date "+%Y-%m-%d-%H") +LAST_OPVER="/tmp/clash_last_version" +version_url="https://github.com/vernesong/OpenClash/raw/master/core_version" +if [ "$CKTIME" != "$(grep "CheckTime" $LAST_OPVER 2>/dev/null |awk -F ':' '{print $2}')" ]; then + wget-ssl --no-check-certificate --quiet --timeout=5 --tries=2 "$version_url" -O $LAST_OPVER + if [ "$?" -eq "0" ] && [ "$(ls -l $LAST_OPVER 2>/dev/null |awk '{print int($5)}')" -gt 0 ]; then + echo "CheckTime:$CKTIME" >>$LAST_OPVER + else + rm -rf $LAST_OPVER + fi +fi \ No newline at end of file diff --git a/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/img/33343e6117c37aaef8886179007ba6b5.png b/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/img/33343e6117c37aaef8886179007ba6b5.png old mode 100755 new mode 100644 diff --git a/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/index.html b/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/index.html old mode 100755 new mode 100644 index 6242f19ebc..58970428e7 --- a/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/index.html +++ b/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/index.html @@ -4,8 +4,8 @@ Clash - +
- + diff --git a/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/1.bundle.09f6f4281ae3598cbadf.min.js b/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/1.bundle.09f6f4281ae3598cbadf.min.js new file mode 100644 index 0000000000..de05dc02e5 --- /dev/null +++ b/package/cnsztl/luci-app-openclash/files/usr/share/openclash/dashboard/js/1.bundle.09f6f4281ae3598cbadf.min.js @@ -0,0 +1,57 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[function(e,t,n){"use strict";e.exports=n(47)},function(e,t,n){"use strict";function r(){return(r=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}n.d(t,"a",function(){return r})},,,function(e,t,n){e.exports=n(51)()},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(48)},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(40)(Object,"create");e.exports=r},function(e,t,n){var r=n(105);e.exports=function(e,t){for(var n=e.length;n--;)if(r(e[n][0],t))return n;return-1}},function(e,t,n){var r=n(111);e.exports=function(e,t){var n=e.__data__;return r(t)?n["string"==typeof t?"string":"hash"]:n.map}},,,function(e,t){var n=Array.isArray;e.exports=n},function(e,t,n){var r=n(39),o=n(84),i="[object Symbol]";e.exports=function(e){return"symbol"==typeof e||o(e)&&r(e)==i}},function(e,t,n){var r=n(22).Symbol;e.exports=r},function(e,t,n){var r=n(81),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();e.exports=i},function(e,t,n){"use strict";n.r(t);var r=n(3),o=n(0),i=n.n(o),a=n(24),l=n.n(a),u=n(11),s=n.n(u),c=n(43),f=n.n(c),d=1073741823;var p=i.a.createContext||function(e,t){var n,r,i="__create-react-context-"+f()()+"__",a=function(e){function n(){var t,n,r;return(t=e.apply(this,arguments)||this).emitter=(n=t.props.value,r=[],{on:function(e){r.push(e)},off:function(e){r=r.filter(function(t){return t!==e})},get:function(){return n},set:function(e,t){n=e,r.forEach(function(e){return e(n,t)})}}),t}l()(n,e);var r=n.prototype;return r.getChildContext=function(){var e;return(e={})[i]=this.emitter,e},r.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,o=e.value;((i=r)===(a=o)?0!==i||1/i==1/a:i!=i&&a!=a)?n=0:(n="function"==typeof t?t(r,o):d,0!=(n|=0)&&this.emitter.set(e.value,n))}var i,a},r.render=function(){return this.props.children},n}(o.Component);a.childContextTypes=((n={})[i]=s.a.object.isRequired,n);var u=function(t){function n(){var e;return(e=t.apply(this,arguments)||this).state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}l()(n,t);var r=n.prototype;return r.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?d:t},r.componentDidMount=function(){this.context[i]&&this.context[i].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?d:e},r.componentWillUnmount=function(){this.context[i]&&this.context[i].off(this.onUpdate)},r.getValue=function(){return this.context[i]?this.context[i].get():e},r.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(o.Component);return u.contextTypes=((r={})[i]=s.a.object,r),{Provider:a,Consumer:u}},h=n(1);function m(e){return"/"===e.charAt(0)}function v(e,t){for(var n=t,r=n+1,o=e.length;r1&&void 0!==arguments[1]?arguments[1]:"",n=e&&e.split("/")||[],r=t&&t.split("/")||[],o=e&&m(e),i=t&&m(t),a=o||i;if(e&&m(e)?r=n:n.length&&(r.pop(),r=r.concat(n)),!r.length)return"/";var l=void 0;if(r.length){var u=r[r.length-1];l="."===u||".."===u||""===u}else l=!1;for(var s=0,c=r.length;c>=0;c--){var f=r[c];"."===f?v(r,c):".."===f?(v(r,c),s++):s&&(v(r,c),s--)}if(!a)for(;s--;s)r.unshift("..");!a||""===r[0]||r[0]&&m(r[0])||r.unshift("");var d=r.join("/");return l&&"/"!==d.substr(-1)&&(d+="/"),d},g="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};var b=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every(function(t,r){return e(t,n[r])});var r=void 0===t?"undefined":g(t);if(r!==(void 0===n?"undefined":g(n)))return!1;if("object"===r){var o=t.valueOf(),i=n.valueOf();if(o!==t||i!==n)return e(o,i);var a=Object.keys(t),l=Object.keys(n);return a.length===l.length&&a.every(function(r){return e(t[r],n[r])})}return!1},w=!0,x="Invariant failed";var _=function(e,t){if(!e)throw w?new Error(x):new Error(x+": "+(t||""))};function S(e){return"/"===e.charAt(0)?e:"/"+e}function T(e){return"/"===e.charAt(0)?e.substr(1):e}function k(e,t){return function(e,t){return new RegExp("^"+t+"(\\/|\\?|#|$)","i").test(e)}(e,t)?e.substr(t.length):e}function C(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function E(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function P(e,t,n,r){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var i=t.indexOf("?");return-1!==i&&(n=t.substr(i),t=t.substr(0,i)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e)).state=t:(void 0===(o=Object(h.a)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(i){throw i instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):i}return n&&(o.key=n),r?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=y(o.pathname,r.pathname)):o.pathname=r.pathname:o.pathname||(o.pathname="/"),o}function O(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.hash===t.hash&&e.key===t.key&&b(e.state,t.state)}function R(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var i="function"==typeof e?e(t,n):e;"string"==typeof i?"function"==typeof r?r(i,o):o(!0):o(!1!==i)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter(function(e){return e!==r})}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;r=0?t:0)+"#"+e)}function $(e){void 0===e&&(e={}),M||_(!1);var t=window.history,n=(window.navigator.userAgent.indexOf("Firefox"),e),r=n.getUserConfirmation,o=void 0===r?I:r,i=n.hashType,a=void 0===i?"slash":i,l=e.basename?C(S(e.basename)):"",u=L[a],s=u.encodePath,c=u.decodePath;function f(){var e=c(U());return l&&(e=k(e,l)),P(e)}var d=R();function p(e){Object(h.a)(j,e),j.length=t.length,d.notifyListeners(j.location,j.action)}var m=!1,v=null;function y(){var e=U(),t=s(e);if(e!==t)F(t);else{var n=f(),r=j.location;if(!m&&O(r,n))return;if(v===E(n))return;v=null,function(e){if(m)m=!1,p();else{d.confirmTransitionTo(e,"POP",o,function(t){t?p({action:"POP",location:e}):function(e){var t=j.location,n=x.lastIndexOf(E(t));-1===n&&(n=0);var r=x.lastIndexOf(E(e));-1===r&&(r=0);var o=n-r;o&&(m=!0,T(o))}(e)})}}(n)}}var g=U(),b=s(g);g!==b&&F(b);var w=f(),x=[E(w)];function T(e){t.go(e)}var z=0;function N(e){1===(z+=e)&&1===e?window.addEventListener(D,y):0===z&&window.removeEventListener(D,y)}var A=!1;var j={length:t.length,action:"POP",location:w,createHref:function(e){return"#"+s(l+E(e))},push:function(e,t){var n=P(e,void 0,void 0,j.location);d.confirmTransitionTo(n,"PUSH",o,function(e){if(e){var t=E(n),r=s(l+t);if(U()!==r){v=t,function(e){window.location.hash=e}(r);var o=x.lastIndexOf(E(j.location)),i=x.slice(0,-1===o?0:o+1);i.push(t),x=i,p({action:"PUSH",location:n})}else p()}})},replace:function(e,t){var n=P(e,void 0,void 0,j.location);d.confirmTransitionTo(n,"REPLACE",o,function(e){if(e){var t=E(n),r=s(l+t);U()!==r&&(v=t,F(r));var o=x.indexOf(E(j.location));-1!==o&&(x[o]=t),p({action:"REPLACE",location:n})}})},go:T,goBack:function(){T(-1)},goForward:function(){T(1)},block:function(e){void 0===e&&(e=!1);var t=d.setPrompt(e);return A||(N(1),A=!0),function(){return A&&(A=!1,N(-1)),t()}},listen:function(e){var t=d.appendListener(e);return N(1),function(){N(-1),t()}}};return j}function W(e,t,n){return Math.min(Math.max(e,t),n)}var H=n(25),B=n.n(H),V=(n(28),n(8)),q=n(44),Q=n.n(q),K=function(e){var t=p();return t.displayName=e,t}("Router"),Y=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen(function(e){n._isMounted?n.setState({location:e}):n._pendingLocation=e})),n}Object(r.a)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){this._isMounted=!0,this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&this.unlisten()},n.render=function(){return i.a.createElement(K.Provider,{children:this.props.children||null,value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}})},t}(i.a.Component);var X=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),o=0;ot?n.splice(t,n.length-t,r):n.push(r),c({action:"PUSH",location:r,index:t,entries:n})}})},replace:function(e,t){var r=P(e,t,f(),y.location);s.confirmTransitionTo(r,"REPLACE",n,function(e){e&&(y.entries[y.index]=r,c({action:"REPLACE",location:r}))})},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=y.index+e;return t>=0&&t=0;t--){var n=e[t][i];n.modified||(Array.isArray(n.base)?P(n)&&_(n):E(n)&&_(n))}}function E(e){for(var t=e.base,n=e.draft,r=Object.keys(n),o=r.length-1;o>=0;o--){var a=r[o],l=t[a];if(void 0===l&&!p(t,a))return!0;var u=n[a],s=u&&u[i];if(s?s.base!==l:!h(u,l))return!0}return r.length!==Object.keys(t).length}function P(e){var t=e.draft;if(t.length!==e.base.length)return!0;var n=Object.getOwnPropertyDescriptor(t,t.length-1);return!(!n||n.get)}var O=Object.freeze({willFinalize:function(e,t,n){e.drafts.forEach(function(e){e[i].finalizing=!0}),n?a(t)&&t[i].scope===e&&C(e.drafts):(e.patches&&function e(t){if(t&&"object"==typeof t){var n=t[i];if(n){var r=n.base,o=n.draft,a=n.assigned;if(Array.isArray(t)){if(P(n)){if(_(n),a.length=!0,o.lengthc&&a[f-1]===l[f+s-1];)--f;for(var d=c;d=f;--v){var y=t.concat([v]);n[m+v-f]={op:"add",path:y,value:l[v]},h&&r.push({op:"remove",path:y})}h||r.push({op:"replace",path:t.concat(["length"]),value:a.length})}(e,t,n,r):function(e,t,n,r){var o=e.base,i=e.copy;f(e.assigned,function(e,a){var l=o[e],u=i[e],s=a?e in o?"replace":"add":"remove";if(l!==u||"replace"!==s){var c=t.concat(e);n.push("remove"===s?{op:s,path:c}:{op:s,path:c,value:u}),r.push("add"===s?{op:"remove",path:c}:"remove"===s?{op:"add",path:c,value:l}:{op:"replace",path:c,value:l})}})}(e,t,n,r)}function L(e,t){for(var n=0;n0;)r[o]=arguments[o+1];return u.produce(e,function(e){return t.call.apply(t,[n,e].concat(r))})}}if("function"!=typeof t)throw new Error("The first or second argument to `produce` must be a function");if(void 0!==n&&"function"!=typeof n)throw new Error("The third argument to `produce` must be a function or undefined");if(l(e)){var s=m.enter(),c=this.createProxy(e),f=!0;try{o=t(c),f=!1}finally{f?s.revoke():s.leave()}return o instanceof Promise?o.then(function(e){return s.usePatches(n),i.processResult(e,s)},function(e){throw s.revoke(),e}):(s.usePatches(n),this.processResult(o,s))}return void 0===(o=t(e))?e:o!==r?o:void 0},F.prototype.createDraft=function(e){if(!l(e))throw new Error("First argument to `createDraft` must be a plain object, an array, or an immerable object");var t=m.enter(),n=this.createProxy(e);return n[i].isManual=!0,t.leave(),n},F.prototype.finishDraft=function(e,t){var n=e&&e[i];if(!n||!n.isManual)throw new Error("First argument to `finishDraft` must be a draft returned by `createDraft`");if(n.finalized)throw new Error("The given draft is already finalized");var r=n.scope;return r.usePatches(t),this.processResult(void 0,r)},F.prototype.setAutoFreeze=function(e){this.autoFreeze=e},F.prototype.setUseProxies=function(e){this.useProxies=e,u(this,e?j:O)},F.prototype.applyPatches=function(e,t){return a(e)?L(e,t):this.produce(e,function(e){return L(e,t)})},F.prototype.processResult=function(e,t){var n=t.drafts[0],o=void 0!==e&&e!==n;if(this.willFinalize(t,e,o),o){if(n[i].modified)throw t.revoke(),new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.");l(e)&&(e=this.finalize(e,null,t)),t.patches&&(t.patches.push({op:"replace",path:[],value:e}),t.inversePatches.push({op:"replace",path:[],value:n[i].base}))}else e=this.finalize(n,[],t);return t.revoke(),t.patches&&t.patchListener(t.patches,t.inversePatches),e!==r?e:void 0},F.prototype.finalize=function(e,t,n){var r=this,o=e[i];if(!o)return Object.isFrozen(e)?e:this.finalizeTree(e,null,n);if(o.scope!==n)return e;if(!o.modified)return o.base;if(!o.finalized){if(o.finalized=!0,this.finalizeTree(o.draft,t,n),this.onDelete)if(this.useProxies){var a=o.assigned;for(var l in a)a[l]||this.onDelete(o,l)}else{var u=o.base,s=o.copy;f(u,function(e){p(s,e)||r.onDelete(o,e)})}this.onCopy&&this.onCopy(o),this.autoFreeze&&n.canAutoFreeze&&Object.freeze(o.copy),t&&n.patches&&D(o,t,n.patches,n.inversePatches)}return o.copy},F.prototype.finalizeTree=function(e,t,n){var r=this,o=e[i];o&&(this.useProxies||(o.copy=c(o.draft,!0)),e=o.copy);var u=!!t&&!!n.patches,s=function(i,c,p){if(c===p)throw Error("Immer forbids circular references");var m=!!o&&p===e;if(a(c)){var v=m&&u&&!o.assigned[i]?t.concat(i):null;if(a(c=r.finalize(c,v,n))&&(n.canAutoFreeze=!1),Array.isArray(p)||d(p,i)?p[i]=c:Object.defineProperty(p,i,{value:c}),m&&c===o.base[i])return}else{if(m&&h(c,o.base[i]))return;l(c)&&!Object.isFrozen(c)&&f(c,s)}m&&r.onAssign&&r.onAssign(o,i,c)};return f(e,s),e};var $=new F,W=$.produce;$.setAutoFreeze.bind($),$.setUseProxies.bind($),$.applyPatches.bind($),$.createDraft.bind($),$.finishDraft.bind($);t.a=W}).call(this,n(33))},function(e,t,n){"use strict"; +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map(function(e){return t[e]}).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(e){r[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(o){return!1}}()?Object.assign:function(e,t){for(var n,l,u=a(e),s=1;s=200&&e<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],function(e){u.headers[e]={}}),r.forEach(["post","put","patch"],function(e){u.headers[e]=r.merge(i)}),e.exports=u}).call(this,n(33))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function l(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var u,s=[],c=!1,f=-1;function d(){c&&u&&(c=!1,u.length?s=u.concat(s):f=-1,s.length&&p())}function p(){if(!c){var e=l(d);c=!0;for(var t=s.length;t;){for(u=s,s=[];++f1)for(var n=1;nI.length&&I.push(e)}function A(e,t,n){return null==e?0:function e(t,n,r,o){var l=typeof t;"undefined"!==l&&"boolean"!==l||(t=null);var u=!1;if(null===t)u=!0;else switch(l){case"string":case"number":u=!0;break;case"object":switch(t.$$typeof){case i:case a:u=!0}}if(u)return r(o,t,""===n?"."+j(t,0):n),1;if(u=0,n=""===n?".":n+":",Array.isArray(t))for(var s=0;sthis.eventPool.length&&this.eventPool.push(e)}function fe(e){e.eventPool=[],e.getPooled=se,e.release=ce}o(ue.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=ae)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=ae)},persist:function(){this.isPersistent=ae},isPersistent:le,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;this.nativeEvent=this._targetInst=this.dispatchConfig=null,this.isPropagationStopped=this.isDefaultPrevented=le,this._dispatchInstances=this._dispatchListeners=null}}),ue.Interface={type:null,target:null,currentTarget:function(){return null},eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null},ue.extend=function(e){function t(){}function n(){return r.apply(this,arguments)}var r=this;t.prototype=r.prototype;var i=new t;return o(i,n.prototype),n.prototype=i,n.prototype.constructor=n,n.Interface=o({},r.Interface,e),n.extend=r.extend,fe(n),n},fe(ue);var de=ue.extend({data:null}),pe=ue.extend({data:null}),he=[9,13,27,32],me=V&&"CompositionEvent"in window,ve=null;V&&"documentMode"in document&&(ve=document.documentMode);var ye=V&&"TextEvent"in window&&!ve,ge=V&&(!me||ve&&8=ve),be=String.fromCharCode(32),we={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["compositionend","keypress","textInput","paste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:"blur compositionend keydown keypress keyup mousedown".split(" ")},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},dependencies:"blur compositionstart keydown keypress keyup mousedown".split(" ")},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:"blur compositionupdate keydown keypress keyup mousedown".split(" ")}},xe=!1;function _e(e,t){switch(e){case"keyup":return-1!==he.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"blur":return!0;default:return!1}}function Se(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Te=!1;var ke={eventTypes:we,extractEvents:function(e,t,n,r){var o=void 0,i=void 0;if(me)e:{switch(e){case"compositionstart":o=we.compositionStart;break e;case"compositionend":o=we.compositionEnd;break e;case"compositionupdate":o=we.compositionUpdate;break e}o=void 0}else Te?_e(e,n)&&(o=we.compositionEnd):"keydown"===e&&229===n.keyCode&&(o=we.compositionStart);return o?(ge&&"ko"!==n.locale&&(Te||o!==we.compositionStart?o===we.compositionEnd&&Te&&(i=ie()):(re="value"in(ne=r)?ne.value:ne.textContent,Te=!0)),o=de.getPooled(o,t,n,r),i?o.data=i:null!==(i=Se(n))&&(o.data=i),B(o),i=o):i=null,(e=ye?function(e,t){switch(e){case"compositionend":return Se(t);case"keypress":return 32!==t.which?null:(xe=!0,be);case"textInput":return(e=t.data)===be&&xe?null:e;default:return null}}(e,n):function(e,t){if(Te)return"compositionend"===e||!me&&_e(e,t)?(e=ie(),oe=re=ne=null,Te=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1