mirror of
https://github.com/kenzok8/small-package.git
synced 2026-02-04 13:57:45 +08:00
update 2026-01-12 00:30:14
This commit is contained in:
@@ -4,11 +4,11 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-natter2
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=4
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI Support for Natter v2.2.1
|
||||
LUCI_PKGARCH:=all
|
||||
LUCI_DEPENDS:=+natter2 +coreutils-nohup
|
||||
LUCI_DEPENDS:=+natter2
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
USE_PROCD=1
|
||||
START=98
|
||||
script_path="/usr/share/natter2/natter.py"
|
||||
|
||||
@@ -11,20 +12,19 @@ start_service() {
|
||||
enable_forwarding forwarding_method target_address target_port \
|
||||
enable_forwarding_retry enable_quit delay log_level enable_notify \
|
||||
notify_path enable_upnp_service"
|
||||
for i in $basic_list
|
||||
do
|
||||
|
||||
for i in $basic_list; do
|
||||
local eval $i="$(uci_get_by_type base 0 $i)"
|
||||
done ; unset i
|
||||
if [ "$enable" == 1 ]
|
||||
then
|
||||
|
||||
if [ "$enable" == 1 ]; then
|
||||
mkdir -p ${tmp_path}
|
||||
mkdir -p /var/etc/natter2
|
||||
for u in $(seq 0 $(($(uci show natter2 2> /dev/null | egrep '@instances\[[0-9]\]+=instances' | wc -l) - 1)))
|
||||
|
||||
for u in $(seq 0 $(($(uci show natter2 2> /dev/null | grep -E '@instances\[[0-9]\]+=instances' | wc -l) - 1)))
|
||||
do
|
||||
for i in $instance_list
|
||||
do
|
||||
for i in $instance_list; do
|
||||
local eval $i="$(uci_get_by_type instances $u $i)"
|
||||
# echo "$i : $(uci_get_by_type instances $u $i)"
|
||||
done ; unset i
|
||||
|
||||
[ "$enable_instance" != 1 ] && continue
|
||||
@@ -32,27 +32,22 @@ start_service() {
|
||||
|
||||
[ "$protocol" == udp ] && script_command="$script_command -u"
|
||||
|
||||
if [ "$enable_stun_server" == 1 ]
|
||||
then
|
||||
for i in $stun_server
|
||||
do
|
||||
if [ "$enable_stun_server" == 1 ]; then
|
||||
for i in $stun_server; do
|
||||
script_command="$script_command -s $i"
|
||||
done ; unset i
|
||||
fi
|
||||
|
||||
[ "$enable_keepalive_server" == 1 ] && script_command="$script_command -h $keepalive_server"
|
||||
[ "$interval" ] && script_command="$script_command -k $interval"
|
||||
|
||||
[ "$enable_upnp_service" == 1 ] && script_command="$script_command -U"
|
||||
|
||||
if [ "$enable_bonding" == 1 ]
|
||||
then
|
||||
if [ "$enable_bonding" == 1 ]; then
|
||||
[ "$bonding_interface" ] && script_command="$script_command -i $bonding_interface"
|
||||
[ "$bonding_port" ] && script_command="$script_command -b $bonding_port"
|
||||
fi
|
||||
|
||||
if [ "$enable_forwarding" == 1 ]
|
||||
then
|
||||
if [ "$enable_forwarding" == 1 ]; then
|
||||
[ "$forwarding_method" ] && script_command="$script_command -m $forwarding_method"
|
||||
[ "$target_address" ] && script_command="$script_command -t $target_address"
|
||||
[ "$target_port" ] && script_command="$script_command -p $target_port"
|
||||
@@ -60,35 +55,30 @@ start_service() {
|
||||
fi
|
||||
|
||||
[ "$enable_quit" == 1 ] && script_command="$script_command -q"
|
||||
|
||||
[ "$log_level" == "verbose" ] && script_command="$script_command -v"
|
||||
|
||||
if [ "$enable_notify" == 1 ]
|
||||
then
|
||||
if [ "$enable_notify" == 1 ]; then
|
||||
echo "$notify_path" > /var/etc/natter2/${id}-notify
|
||||
var_file=/var/etc/natter2/${id}-${u}-1
|
||||
else
|
||||
var_file=/var/etc/natter2/${id}-${u}-0
|
||||
fi
|
||||
|
||||
log_file=${tmp_path}/natter2-${id}.log
|
||||
|
||||
cp -a /usr/share/luci-app-natter2/notify-base.sh $var_file
|
||||
chmod +x $var_file
|
||||
|
||||
# echo "log_file: $log_file"
|
||||
# echo "var_file: $var_file"
|
||||
procd_open_instance "natter2_${id}"
|
||||
procd_set_param command $(command -v python) "$script_path" $script_command -e $var_file
|
||||
|
||||
sleep $delay
|
||||
for i in $(ps -efww | grep "$script_path" | grep -v grep | grep -v $$ | grep "$id" | awk '{print $1}')
|
||||
do
|
||||
kill -9 "$i" 2> /dev/null
|
||||
done
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
|
||||
nohup $(command -v python) "$script_path" $script_command -e $var_file > "$log_file" 2>&1 &
|
||||
[ -n "$delay" ] && procd_set_param delay "$delay"
|
||||
procd_set_param respawn
|
||||
|
||||
for i in $instance_list
|
||||
do
|
||||
procd_close_instance
|
||||
|
||||
for i in $instance_list; do
|
||||
unset $(echo $i)
|
||||
done ; unset i
|
||||
unset script_command
|
||||
@@ -99,24 +89,13 @@ start_service() {
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
echo "Stopping Natter2 ..."
|
||||
for i in $(ps -ww | grep "$script_path" | grep -v grep | grep -v $$ | awk '{print $1}')
|
||||
do
|
||||
kill -15 "$i" 2> /dev/null
|
||||
done
|
||||
rm -r "$tmp_path" 2> /dev/null
|
||||
for u in $(seq 0 $(($(uci show natter2 2> /dev/null | egrep '@instances\[[0-9]\]+=instances' | wc -l) - 1)))
|
||||
rm -rf "/var/etc/natter2" 2> /dev/null
|
||||
for u in $(seq 0 $(($(uci show natter2 2> /dev/null | grep -E '@instances\[[0-9]\]+=instances' | wc -l) - 1)))
|
||||
do
|
||||
uci set natter2.@instances[$u].tmp_public_port=""
|
||||
uci commit natter2
|
||||
done
|
||||
rm -f /tmp/natter2_nat_type
|
||||
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop_service
|
||||
start_service
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
@@ -126,4 +105,4 @@ service_triggers() {
|
||||
uci_get_by_type() {
|
||||
local ret=$(uci get natter2.@$1[$2].$3 2>/dev/null)
|
||||
echo ${ret:=$4}
|
||||
}
|
||||
}
|
||||
@@ -243,6 +243,6 @@ o.cfgvalue = function(self, section)
|
||||
section, translate("Manual subscription"))
|
||||
end
|
||||
|
||||
s:append(Template(appname .. "/node_subscribe/js"))
|
||||
m:append(Template(appname .. "/node_subscribe/js"))
|
||||
|
||||
return m
|
||||
|
||||
@@ -4,12 +4,10 @@ local api = require "luci.passwall.api"
|
||||
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js?v=26.1.9"></script>
|
||||
|
||||
<style>
|
||||
<% if api.is_js_luci() then -%>
|
||||
table .cbi-button-up,
|
||||
table .cbi-button-down {
|
||||
display: none !important;
|
||||
}
|
||||
<%- end %>
|
||||
|
||||
.drag-handle {
|
||||
cursor: grab !important;
|
||||
@@ -21,7 +19,6 @@ table .cbi-button-down {
|
||||
padding: 0 !important;
|
||||
line-height: inherit;
|
||||
user-select: none;
|
||||
color: #00000070;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
@@ -83,6 +80,8 @@ table .cbi-button-down {
|
||||
var section = document.getElementById("cbi-<%=api.appname%>-haproxy_config");
|
||||
if (!section) return;
|
||||
|
||||
hideSortColumn(section);
|
||||
|
||||
// === 插入 drag handle ===
|
||||
var delBtns = section.getElementsByClassName("cbi-button-remove");
|
||||
for (var i = 0; i < delBtns.length; i++) {
|
||||
@@ -150,6 +149,37 @@ table .cbi-button-down {
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏18.06 up/down 列
|
||||
function hideSortColumn(section) {
|
||||
var table = section.querySelector("table");
|
||||
if (!table) return;
|
||||
var ths = Array.prototype.slice.call(table.querySelectorAll("tr.cbi-section-table-titles > th"));
|
||||
var dataRows = table.querySelectorAll("tr.cbi-section-table-row");
|
||||
if (!ths.length || !dataRows.length) return;
|
||||
var sortCol = -1;
|
||||
for (var i = 0; i < ths.length; i++) {
|
||||
var hasSort = false, invalid = false;
|
||||
dataRows.forEach(function(tr) {
|
||||
var td = tr.querySelectorAll(":scope > td")[i];
|
||||
if (!td) return;
|
||||
if (td.querySelector(".cbi-button-edit, .cbi-button-remove")) invalid = true;
|
||||
if (td.querySelector(".cbi-button-up, .cbi-button-down")) hasSort = true;
|
||||
});
|
||||
if (!invalid && hasSort) { sortCol = i; break; }
|
||||
}
|
||||
if (sortCol === -1) return;
|
||||
var rows = [table.querySelector("tr.cbi-section-table-titles")].concat(
|
||||
Array.prototype.slice.call(dataRows),
|
||||
Array.prototype.slice.call(table.querySelectorAll("tr.cbi-section-table-descr"))
|
||||
);
|
||||
rows.forEach(function(tr) {
|
||||
var cells = Array.prototype.filter.call(tr.children, function(el) {
|
||||
return el.tagName === "TH" || el.tagName === "TD";
|
||||
});
|
||||
if (cells[sortCol]) cells[sortCol].style.display = "none";
|
||||
});
|
||||
}
|
||||
|
||||
// === 等待 TypedSection 行稳定 ===
|
||||
(function waitStable() {
|
||||
var last = 0, stable = 0;
|
||||
|
||||
@@ -68,7 +68,6 @@ table td, .table .td {
|
||||
padding: 0 !important;
|
||||
line-height: inherit;
|
||||
user-select: none;
|
||||
color: #00000070;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,33 @@
|
||||
<%
|
||||
local api = require "luci.passwall.api"
|
||||
-%>
|
||||
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js?v=26.1.11"></script>
|
||||
|
||||
<style>
|
||||
table .cbi-button-up,
|
||||
table .cbi-button-down {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
cursor: grab !important;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
font-weight: 100;
|
||||
padding: 0 !important;
|
||||
line-height: inherit;
|
||||
user-select: none;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.dragging-row {
|
||||
background-color: rgba(131, 191, 255, 0.7) !important;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var appname = "<%= api.appname %>"
|
||||
@@ -107,5 +134,131 @@ local api = require "luci.passwall.api"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//订阅列表添加拖拽排序
|
||||
(function () {
|
||||
function initSortableForTable() {
|
||||
var section = document.getElementById("cbi-<%=api.appname%>-subscribe_list");
|
||||
if (!section) return;
|
||||
|
||||
hideSortColumn(section);
|
||||
|
||||
// === 插入 drag handle ===
|
||||
var delBtns = section.getElementsByClassName("cbi-button-remove");
|
||||
for (var i = 0; i < delBtns.length; i++) {
|
||||
var btnsInRow = delBtns[i].closest("tr").getElementsByClassName("cbi-button-remove");
|
||||
if (!btnsInRow || btnsInRow.length === 0) continue;
|
||||
var btn = btnsInRow[btnsInRow.length - 1];
|
||||
var parent = btn && btn.parentNode;
|
||||
if (!parent || parent.getElementsByClassName("drag-handle").length) continue;
|
||||
var handle = document.createElement("span");
|
||||
handle.className = "drag-handle center";
|
||||
handle.title = "<%:Drag to reorder%>";
|
||||
handle.innerHTML = "⠿";
|
||||
parent.insertBefore(handle, btn.nextSibling);
|
||||
}
|
||||
|
||||
// === 初始化 Sortable ===
|
||||
var table = section.getElementsByTagName("table")[0];
|
||||
if (!table) return;
|
||||
var root = table.tBodies[0] || table;
|
||||
if (root._sortable_initialized) return root._sortable_instance;
|
||||
root._sortable_initialized = true;
|
||||
|
||||
// 保存原始顺序
|
||||
root._origOrder = getCurrentOrder(root);
|
||||
|
||||
try {
|
||||
root._sortable_instance = Sortable.create(root, {
|
||||
handle: ".drag-handle",
|
||||
draggable: "tr.cbi-section-table-row",
|
||||
animation: 150,
|
||||
ghostClass: "dragging-row",
|
||||
fallbackOnBody: true,
|
||||
forceFallback: false,
|
||||
swapThreshold: 0.65,
|
||||
onEnd: function (evt) {
|
||||
updateHiddenInput(root, section);
|
||||
}
|
||||
});
|
||||
return root._sortable_instance;
|
||||
} catch (e) {
|
||||
root._sortable_initialized = false;
|
||||
console.error("Sortable init failed:", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取 table 当前行顺序
|
||||
function getCurrentOrder(root) {
|
||||
var order = [];
|
||||
var rows = root.querySelectorAll("tr.cbi-section-table-row");
|
||||
rows.forEach(function (tr) {
|
||||
var id = tr.id || "";
|
||||
if (id.startsWith("cbi-<%=api.appname%>-"))
|
||||
id = id.replace("cbi-<%=api.appname%>-", "");
|
||||
order.push(id);
|
||||
});
|
||||
return order;
|
||||
}
|
||||
|
||||
// 拖拽完成后更新 hidden input
|
||||
function updateHiddenInput(root, section) {
|
||||
var newOrder = getCurrentOrder(root);
|
||||
var changed = newOrder.join(" ") !== root._origOrder.join(" ");
|
||||
var hiddenInput = section.querySelector('input[type="hidden"][id^="cbi.sts."]');
|
||||
if (hiddenInput) {
|
||||
hiddenInput.value = changed ? newOrder.join(" ") : "";
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏18.06 up/down 列
|
||||
function hideSortColumn(section) {
|
||||
var table = section.querySelector("table");
|
||||
if (!table) return;
|
||||
var ths = Array.prototype.slice.call(table.querySelectorAll("tr.cbi-section-table-titles > th"));
|
||||
var dataRows = table.querySelectorAll("tr.cbi-section-table-row");
|
||||
if (!ths.length || !dataRows.length) return;
|
||||
var sortCol = -1;
|
||||
for (var i = 0; i < ths.length; i++) {
|
||||
var hasSort = false, invalid = false;
|
||||
dataRows.forEach(function(tr) {
|
||||
var td = tr.querySelectorAll(":scope > td")[i];
|
||||
if (!td) return;
|
||||
if (td.querySelector(".cbi-button-edit, .cbi-button-remove")) invalid = true;
|
||||
if (td.querySelector(".cbi-button-up, .cbi-button-down")) hasSort = true;
|
||||
});
|
||||
if (!invalid && hasSort) { sortCol = i; break; }
|
||||
}
|
||||
if (sortCol === -1) return;
|
||||
var rows = [table.querySelector("tr.cbi-section-table-titles")].concat(
|
||||
Array.prototype.slice.call(dataRows),
|
||||
Array.prototype.slice.call(table.querySelectorAll("tr.cbi-section-table-descr"))
|
||||
);
|
||||
rows.forEach(function(tr) {
|
||||
var cells = Array.prototype.filter.call(tr.children, function(el) {
|
||||
return el.tagName === "TH" || el.tagName === "TD";
|
||||
});
|
||||
if (cells[sortCol]) cells[sortCol].style.display = "none";
|
||||
});
|
||||
}
|
||||
|
||||
// === 等待 TypedSection 行稳定 ===
|
||||
(function waitStable() {
|
||||
var last = 0, stable = 0;
|
||||
var THRESHOLD = 5;
|
||||
function tick() {
|
||||
var count = document.querySelectorAll("tr.cbi-section-table-row").length;
|
||||
if (count && count === last) stable++;
|
||||
else stable = 0;
|
||||
|
||||
last = count;
|
||||
if (stable >= THRESHOLD)
|
||||
initSortableForTable();
|
||||
else
|
||||
requestAnimationFrame(tick);
|
||||
}
|
||||
tick();
|
||||
})();
|
||||
})();
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
@@ -4,12 +4,10 @@ local api = require "luci.passwall.api"
|
||||
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js?v=26.1.9"></script>
|
||||
|
||||
<style>
|
||||
<% if api.is_js_luci() then -%>
|
||||
table .cbi-button-up,
|
||||
table .cbi-button-down {
|
||||
display: none !important;
|
||||
}
|
||||
<%- end %>
|
||||
|
||||
div.cbi-value[id$="-gfwlist_update"],
|
||||
div.cbi-value[id$="-chnroute_update"],
|
||||
@@ -30,7 +28,6 @@ local api = require "luci.passwall.api"
|
||||
padding: 0 !important;
|
||||
line-height: inherit;
|
||||
user-select: none;
|
||||
color: #00000070;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
@@ -150,6 +147,8 @@ local api = require "luci.passwall.api"
|
||||
var section = document.getElementById("cbi-<%=api.appname%>-shunt_rules");
|
||||
if (!section) return;
|
||||
|
||||
hideSortColumn(section);
|
||||
|
||||
// === 插入 drag handle ===
|
||||
var delBtns = section.getElementsByClassName("cbi-button-remove");
|
||||
for (var i = 0; i < delBtns.length; i++) {
|
||||
@@ -216,6 +215,28 @@ local api = require "luci.passwall.api"
|
||||
hiddenInput.value = changed ? newOrder.join(" ") : "";
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏18.06 up/down 列
|
||||
function hideSortColumn(section) {
|
||||
var table = section.getElementsByTagName("table")[0];
|
||||
if(!table) return;
|
||||
var rows = table.querySelectorAll("tr.cbi-section-table-row");
|
||||
if(!rows.length) return;
|
||||
var colCount = rows[0].children.length, sortCol = -1;
|
||||
for(var col=0; col<colCount; col++){
|
||||
var hasSort=false, invalid=false;
|
||||
rows.forEach(function(tr){
|
||||
var td=tr.children[col]; if(!td) return;
|
||||
if(td.querySelector(".cbi-button-edit, .cbi-button-remove")) invalid=true;
|
||||
if(td.querySelector(".cbi-button-up, .cbi-button-down")) hasSort=true;
|
||||
});
|
||||
if(!invalid && hasSort){ sortCol=col; break; }
|
||||
}
|
||||
if(sortCol===-1) return;
|
||||
table.querySelectorAll("tr").forEach(function(tr){
|
||||
var c=tr.children[sortCol]; if(c) c.style.display="none";
|
||||
});
|
||||
}
|
||||
|
||||
// === 等待 TypedSection 行稳定 ===
|
||||
(function waitStable() {
|
||||
|
||||
@@ -21,13 +21,13 @@ define Download/geoip
|
||||
HASH:=ed2de9add79623e2e5dbc5930ee39cc7037a7c6e0ecd58ba528b6f73d61457b5
|
||||
endef
|
||||
|
||||
GEOSITE_VER:=20260110143056
|
||||
GEOSITE_VER:=20260111140131
|
||||
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
||||
define Download/geosite
|
||||
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
||||
URL_FILE:=dlc.dat
|
||||
FILE:=$(GEOSITE_FILE)
|
||||
HASH:=967c3f444b62de133dbd55f02b4117e4afd61168b6cb8fafa2c79d59324e4414
|
||||
HASH:=60aa9988750f09431ad989e952afe0de0c08a5df18a9b867fc679ccbfc8c62de
|
||||
endef
|
||||
|
||||
GEOSITE_IRAN_VER:=202601050049
|
||||
|
||||
Reference in New Issue
Block a user