update 2024-12-08 20:38:20

This commit is contained in:
kenzok8 2024-12-08 20:38:20 +08:00
parent 99d22eaa8d
commit c54ed1e363
16 changed files with 96 additions and 181 deletions

View File

@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=floatip
PKG_VERSION:=1.0.1
PKG_VERSION:=1.0.2
PKG_RELEASE:=1
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>

View File

@ -6,7 +6,9 @@ config floatip 'main'
# option role 'main'
# 对于 fallback 节点,检查到 check_ip 都不在线超过一定时间例如30秒就设置自身的 set_ip然后检查 check_ip 中任一 IP 在线就清除自身的 set_ip重复上述流程。
# 对于 main 节点,启动后不断检查 set_ip ,直到 set_ip 不在线,就设置自身的 set_ip然后退出进程。
# set_ip 可以不提供前缀长度,将会按 lan 口配置的网段的长度
option set_ip '192.168.100.3/24'
# option set_ip '192.168.100.3'
# check_ip 仅 fallback 有效,并且检查时只检查跟 set_ip 同一网段的
list check_ip '192.168.100.2'
# list check_ip '192.168.100.4'

View File

@ -14,7 +14,7 @@ start_service() {
[[ -n "$set_ip" ]] || return 0
eval "$(ipcalc.sh "$set_ip" )";set_prefix=$PREFIX;set_ip=$IP
[[ "$set_ip" = 0.0.0.0 ]] && set_ip=192.168.100.3
[[ "$set_prefix" = 0 ]] && set_prefix=24
[[ "$set_prefix" = 0 ]] && set_prefix=32
local lan_ip="`uci -q get network.lan.ipaddr`"
[[ -n "$lan_ip" ]] || return 0
local lan_net lan_prefix set_net ip
@ -25,6 +25,7 @@ start_service() {
[[ "$set_prefix" -ge "$lan_prefix" ]] || continue
eval "$(ipcalc.sh $set_ip $lan_prefix } )";set_net=$NETWORK
[[ "$set_net" = "$lan_net" ]] && {
[[ "$set_prefix" = 32 ]] && set_prefix=$lan_prefix
in_range=1
break
}
@ -34,12 +35,15 @@ start_service() {
eval "$(ipcalc.sh "$lan_ip" "$netmask" )";lan_net=$NETWORK;lan_prefix=$PREFIX
if [[ "$set_prefix" -ge "$lan_prefix" ]]; then
eval "$(ipcalc.sh $set_ip $lan_prefix } )";set_net=$NETWORK
[[ "$set_net" = "$lan_net" ]] && in_range=1
if [[ "$set_net" = "$lan_net" ]]; then
[[ "$set_prefix" = 32 ]] && set_prefix=$lan_prefix
in_range=1
fi
fi
fi
[[ $in_range = 1 ]] || return 0
procd_open_instance
procd_set_param command /usr/libexec/floatip.sh
procd_set_param command /usr/libexec/floatip.sh "$set_prefix"
procd_set_param stderr 1
procd_set_param file /etc/config/floatip
procd_close_instance

View File

@ -1,5 +1,7 @@
#!/bin/sh
DEFAULT_PREFIX=24
# random number 0-255
random() {
local num=$(dd if=/dev/urandom bs=1 count=1 2>/dev/null | hexdump -ve '1/1 "%u"')
@ -44,7 +46,7 @@ fallback_loop() {
config_get check_ip "main" check_ip
eval "$(ipcalc.sh "$set_ip" )";set_net=$NETWORK;set_prefix=$PREFIX;set_ip=$IP
[[ "$set_net" = 0.0.0.0 ]] && set_net=192.168.100.0
[[ "$set_prefix" = 0 ]] && set_prefix=24
[[ "$set_prefix" = 0 ]] && set_prefix=$DEFAULT_PREFIX
[[ "$set_ip" = 0.0.0.0 ]] && set_ip=192.168.100.3
local ipaddr="$set_ip/$set_prefix"
local valid_check_ip cip
@ -103,7 +105,7 @@ main_loop() {
config_get set_ip "main" set_ip
eval "$(ipcalc.sh "$set_ip" )";set_net=$NETWORK;set_prefix=$PREFIX;set_ip=$IP
[[ "$set_net" = 0.0.0.0 ]] && set_net=192.168.100.0
[[ "$set_prefix" = 0 ]] && set_prefix=24
[[ "$set_prefix" = 0 ]] && set_prefix=$DEFAULT_PREFIX
[[ "$set_ip" = 0.0.0.0 ]] && set_ip=192.168.100.3
local ipaddr="$set_ip/$set_prefix"
while :; do
@ -131,4 +133,6 @@ main() {
fi
}
[[ -n "$1" && "$1" -ge 0 && "$1" -lt 32 ]] && DEFAULT_PREFIX=$1
main

View File

@ -28,7 +28,6 @@ include $(INCLUDE_DIR)/package.mk
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) $(CURDIR)/root $(PKG_BUILD_DIR)
$(CP) $(CURDIR)/luasrc $(PKG_BUILD_DIR)
$(CP) $(CURDIR)/htdocs $(PKG_BUILD_DIR)
chmod 0755 $(PKG_BUILD_DIR)/root/usr/bin/nekobox
chmod 0755 $(PKG_BUILD_DIR)/root/etc/init.d/neko
@ -89,10 +88,8 @@ endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc/neko
$(INSTALL_DIR) $(1)/usr/lib/lua/luci
$(INSTALL_DIR) $(1)/www/nekobox
$(INSTALL_DIR) $(1)/www
$(CP) $(PKG_BUILD_DIR)/root/* $(1)/
$(CP) $(PKG_BUILD_DIR)/luasrc/* $(1)/usr/lib/lua/luci/
$(CP) $(PKG_BUILD_DIR)/htdocs/* $(1)/www/
endef

View File

@ -0,0 +1,18 @@
'use strict';
'require view';
'require uci';
return view.extend({
load: function() {
return uci.load('neko');
},
render: function() {
return E('iframe', {
src: window.location.protocol + "//" + window.location.hostname + '/nekobox',
style: 'width: 100%; min-height: 95vh; border: none; border-radius: 5px; resize: vertical;'
});
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View File

@ -0,0 +1,26 @@
'use strict';
'require view';
'require uci';
return view.extend({
load: function() {
return uci.load('neko');
},
render: async function() {
const url_data = await fetch('/nekobox/lib/log.php?data=url_dash').then(function (response) {
return response.json();
}).then(function (data){
return data;
}).catch(function (error) {
console.log(error);
});
return E('iframe', {
src: url_data.zash,
style: 'width: 100%; min-height: 95vh; border: none; border-radius: 5px; resize: vertical;'
});
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});

View File

@ -173,7 +173,7 @@ EOL;
<form method="post" action="">
<div class="mb-3">
<label for="subscribeUrl" class="form-label">订阅链接地址:</label>
<input type="text" class="form-control" id="subscribeUrl" name="subscribeUrl" value="<?php echo htmlspecialchars($lastSubscribeUrl); ?>" placeholder="输入订阅链接" required>
<input type="text" class="form-control" id="subscribeUrl" name="subscribeUrl" value="<?php echo htmlspecialchars($lastSubscribeUrl); ?>" placeholder="输入订阅链接(多个链接用 | 分隔)" required>
</div>
<div class="mb-3">
<label for="customFileName" class="form-label">自定义文件名(无需输入后缀)</label>

View File

@ -13,10 +13,10 @@ if(isset($_GET['data'])){
else if($dt == 'url_dash'){
header("Content-type: application/json; charset=utf-8");
$yacd = exec (" curl -m 5 -f -s $host_now/nekobox/dashboard.php | grep 'href=\"h' | cut -d '\"' -f6 | head -1");
$meta = exec (" curl -m 5 -f -s $host_now/nekobox/dashboard.php | grep 'href=\"h' | cut -d '\"' -f6 | tail -1");
$zash = exec (" curl -m 5 -f -s $host_now/nekobox/dashboard.php | grep 'href=\"h' | cut -d '\"' -f6 | tail -1");
echo "{\n";
echo " \"yacd\":\"$yacd\",\n";
echo " \"meta\":\"$meta\"\n";
echo " \"zash\":\"$zash\"\n";
echo "}";
}
}

View File

@ -231,7 +231,7 @@
fetch("/nekobox/lib/log.php?data=url_dash")
.then(response => response.json())
.then(data => {
document.getElementById("neko").src = data.meta;
document.getElementById("neko").src = data.zash;
})
.catch(error => {
console.error("Error fetching URL data:", error);

View File

@ -1,37 +0,0 @@
module("luci.controller.neko", package.seeall)
function index()
entry({"admin","services","neko"}, template("neko"), _("NekoBox"), 1).leaf=true
entry({"admin", "services", "neko", "mon"}, template("neko_mon"), nil, 2).leaf = true
entry({"admin", "services", "neko", "logs"}, call("render_logs"), nil, 3).leaf = true
entry({"admin", "services", "neko", "fetch_plugin_log"}, call("fetch_plugin_log")).leaf = true
entry({"admin", "services", "neko", "fetch_mihomo_log"}, call("fetch_mihomo_log")).leaf = true
entry({"admin", "services", "neko", "fetch_singbox_log"}, call("fetch_singbox_log")).leaf = true
end
function render_logs()
if luci.http.formvalue("clear_plugin_log") then
luci.sys.exec("echo '' > /etc/neko/tmp/log.txt")
elseif luci.http.formvalue("clear_mihomo_log") then
luci.sys.exec("echo '' > /etc/neko/tmp/neko_log.txt")
elseif luci.http.formvalue("clear_singbox_log") then
luci.sys.exec("echo '' > /var/log/singbox_log.txt")
end
luci.template.render("neko_logs")
end
function fetch_plugin_log()
luci.http.prepare_content("text/plain")
luci.http.write(luci.sys.exec("cat /etc/neko/tmp/log.txt"))
end
function fetch_mihomo_log()
luci.http.prepare_content("text/plain")
luci.http.write(luci.sys.exec("cat /etc/neko/tmp/neko_log.txt"))
end
function fetch_singbox_log()
luci.http.prepare_content("text/plain")
luci.http.write(luci.sys.exec("cat /var/log/singbox_log.txt"))
end

View File

@ -1,8 +0,0 @@
<%+header%>
<div class="cbi-map">
<iframe id="neko" style="width: 100%; min-height: 100vh; border: none; border-radius: 5px;"></iframe>
</div>
<script type="text/javascript">
document.getElementById("neko").src = window.location.protocol + "//" + window.location.host + "/nekobox";
</script>
<%+footer%>

View File

@ -1,112 +0,0 @@
<%+header%>
<div class="container-fluid container-bg border border-3 rounded-4 col-12 mb-4">
<div class="log-container" style="width: 100%;">
<div class="log-section p-3 mb-4" style="width: 100%; background-color: #000;">
<h2 class="log-header text-primary">Neko 日志</h2>
<div class="border rounded-4 p-2" style="border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 10px;">
<pre id="plugin_log" class="form-control" style="height: 400px; overflow-y: scroll; background-color: #000; color: #fff; border: none;"><%= luci.sys.exec("cat /etc/neko/tmp/log.txt") %></pre>
</div>
<form action="<%= luci.dispatcher.build_url('admin/services/neko/logs') %>" method="post" class="mt-3 log-footer">
<button type="submit" name="clear_plugin_log" class="btn btn-danger btn-clear-log" style="background-color: #dc3545;">清空日志</button>
</form>
</div>
<div class="log-section p-3 mb-4" style="width: 100%; background-color: #000;">
<h2 class="log-header text-success">Mihomo 日志</h2>
<div class="border rounded-4 p-2" style="border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 10px;">
<pre id="mihomo_log" class="form-control" style="height: 400px; overflow-y: scroll; background-color: #000; color: #fff; border: none;"><%= luci.sys.exec("cat /etc/neko/tmp/neko_log.txt") %></pre>
</div>
<form action="<%= luci.dispatcher.build_url('admin/services/neko/logs') %>" method="post" class="mt-3 log-footer">
<button type="submit" name="clear_mihomo_log" class="btn btn-warning btn-clear-log" style="background-color: #ffc107;">清空日志</button>
</form>
</div>
<div class="log-section p-3 mb-4" style="width: 100%; background-color: #000;">
<h2 class="log-header text-info">Sing-box 日志</h2>
<div class="border rounded-4 p-2" style="border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 10px;">
<pre id="singbox_log" class="form-control" style="height: 400px; overflow-y: scroll; background-color: #000; color: #fff; border: none;"><%= luci.sys.exec("cat /var/log/singbox_log.txt") %></pre>
</div>
<form action="<%= luci.dispatcher.build_url('admin/services/neko/logs') %>" method="post" class="mt-3 log-footer">
<button type="submit" name="clear_singbox_log" class="btn btn-primary btn-clear-log" style="background-color: #007bff;">清空日志</button>
</form>
</div>
</div>
<div class="form-check form-switch text-center">
<input class="form-check-input" type="checkbox" id="autoRefreshToggle" checked>
<label class="form-check-label" for="autoRefreshToggle" style="color: #fff;">自动刷新</label>
</div>
</div>
<style>
.btn-clear-log {
margin-top: 10px;
padding: 10px 20px;
border-radius: 5px;
border: none;
cursor: pointer;
}
.btn-danger {
background-color: #dc3545;
color: white;
}
.btn-warning {
background-color: #ffc107;
color: black;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-danger:hover, .btn-warning:hover, .btn-primary:hover {
opacity: 0.8;
}
</style>
<script>
let autoRefreshEnabled = true;
document.getElementById('autoRefreshToggle').addEventListener('change', function() {
autoRefreshEnabled = this.checked;
});
function scrollToBottom(elementId) {
var logElement = document.getElementById(elementId);
logElement.scrollTop = logElement.scrollHeight;
}
function fetchLogs() {
if (autoRefreshEnabled) {
fetch('<%= luci.dispatcher.build_url("admin/services/neko/fetch_plugin_log") %>')
.then(response => response.text())
.then(data => {
var pluginLog = document.getElementById('plugin_log');
pluginLog.textContent = data;
scrollToBottom('plugin_log');
});
fetch('<%= luci.dispatcher.build_url("admin/services/neko/fetch_mihomo_log") %>')
.then(response => response.text())
.then(data => {
var mihomoLog = document.getElementById('mihomo_log');
mihomoLog.textContent = data;
scrollToBottom('mihomo_log');
});
fetch('<%= luci.dispatcher.build_url("admin/services/neko/fetch_singbox_log") %>')
.then(response => response.text())
.then(data => {
var singboxLog = document.getElementById('singbox_log');
singboxLog.textContent = data;
scrollToBottom('singbox_log');
});
}
}
setInterval(fetchLogs, 5000);
</script>
<%+footer%>

View File

@ -1,8 +0,0 @@
<%+header%>
<div class="cbi-map">
<iframe id="neko" style="width: 100%; min-height: 100vh; border: none; border-radius: 5px;"></iframe>
</div>
<script type="text/javascript">
document.getElementById("neko").src = window.location.protocol + "//" + window.location.host + "/nekobox/mon.php";
</script>
<%+footer%>

View File

@ -0,0 +1,29 @@
{
"admin/services/nekobox": {
"title": "NekoBox",
"action": {
"type": "firstchild"
},
"depends": {
"acl": [ "luci-app-nekobox" ]
}
},
"admin/services/nekobox/nekobox": {
"title": "首页",
"order": 1,
"action": {
"type": "view",
"path": "nekobox/nekobox"
}
},
"admin/services/nekobox/zashboard": {
"title": "面板",
"order": 2,
"action": {
"type": "view",
"path": "nekobox/zashboard"
}
}
}

View File

@ -2,10 +2,10 @@
"luci-app-nekobox": {
"description": "Grant UCI access for luci-app-nekobox",
"read": {
"uci": [ "neko" ]
"uci": [ "nekobox" ]
},
"write": {
"uci": [ "neko" ]
"uci": [ "nekobox" ]
}
}
}