small-package/luci-app-nekobox/htdocs/nekobox/subscription.php

922 lines
54 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
ob_start();
include './cfg.php';
ini_set('memory_limit', '256M');
$result = $result ?? '';
$subscription_file = '/etc/neko/tmp/singbox.txt';
$download_path = '/etc/neko/config/';
$log_file = '/var/log/neko_update.log';
$current_subscription_url = '';
if (isset($_POST['subscription_url'])) {
$current_subscription_url = $_POST['subscription_url'];
}
function logMessage($message) {
global $log_file;
$timestamp = date('Y-m-d H:i:s');
file_put_contents($log_file, "[$timestamp] $message\n", FILE_APPEND);
}
function buildFinalUrl($subscription_url, $config_url, $include, $exclude, $backend_url, $emoji, $udp, $xudp, $tfo, $ipv6, $tls13, $fdn, $sort, $rename) {
$encoded_subscription_url = urlencode($subscription_url);
$encoded_config_url = urlencode($config_url);
$encoded_include = urlencode($include);
$encoded_exclude = urlencode($exclude);
$encoded_rename = urlencode($rename);
$final_url = "{$backend_url}target=singbox&url={$encoded_subscription_url}&insert=false&config={$encoded_config_url}";
if (!empty($include)) {
$final_url .= "&include={$encoded_include}";
}
if (!empty($exclude)) {
$final_url .= "&exclude={$encoded_exclude}";
}
$final_url .= "&emoji=" . (isset($_POST['emoji']) && $_POST['emoji'] === 'true' ? "true" : "false");
$final_url .= "&xudp=" . (isset($_POST['xudp']) && $_POST['xudp'] === 'true' ? "true" : "false");
$final_url .= "&udp=" . (isset($_POST['udp']) && $_POST['udp'] === 'true' ? "true" : "false");
$final_url .= "&tfo=" . (isset($_POST['tfo']) && $_POST['tfo'] === 'true' ? "true" : "false");
$final_url .= "&fdn=" . (isset($_POST['fdn']) && $_POST['fdn'] === 'true' ? "true" : "false");
$final_url .= "&tls13=" . (isset($_POST['tls13']) && $_POST['tls13'] === 'true' ? "true" : "false");
$final_url .= "&sort=" . (isset($_POST['sort']) && $_POST['sort'] === 'true' ? "true" : "false");
$final_url .= "&list=false&expand=true&scv=false";
if (!empty($rename)) {
$final_url .= "&rename={$encoded_rename}";
}
if ($ipv6 === 'true') {
$final_url .= "&singbox.ipv6=1";
}
return $final_url;
}
function saveSubscriptionUrlToFile($url, $file) {
$success = file_put_contents($file, $url) !== false;
logMessage($success ? "订阅链接已保存到 $file" : "保存订阅链接失败到 $file");
return $success;
}
function transformContent($content) {
$parsedData = json_decode($content, true);
if ($parsedData === null) {
logMessage("无法解析内容为 JSON 格式");
return "无法解析内容为 JSON 格式";
}
if (isset($parsedData['inbounds'])) {
$newInbounds = [];
foreach ($parsedData['inbounds'] as $inbound) {
if (isset($inbound['type']) && $inbound['type'] === 'mixed' && $inbound['tag'] === 'mixed-in') {
if ($inbound['listen_port'] !== 2080) {
$newInbounds[] = $inbound;
}
} elseif (isset($inbound['type']) && $inbound['type'] === 'tun') {
continue;
}
}
$newInbounds[] = [
"domain_strategy" => "prefer_ipv4",
"listen" => "127.0.0.1",
"listen_port" => 2334,
"sniff" => true,
"sniff_override_destination" => true,
"tag" => "mixed-in",
"type" => "mixed",
"users" => []
];
$newInbounds[] = [
"tag" => "tun",
"type" => "tun",
"address" => [
"172.19.0.1/30",
"fdfe:dcba:9876::1/126"
],
"route_address" => [
"0.0.0.0/1",
"128.0.0.0/1",
"::/1",
"8000::/1"
],
"route_exclude_address" => [
"192.168.0.0/16",
"fc00::/7"
],
"stack" => "system",
"auto_route" => true,
"strict_route" => true,
"sniff" => true,
"platform" => [
"http_proxy" => [
"enabled" => true,
"server" => "0.0.0.0",
"server_port" => 1082
]
]
];
$newInbounds[] = [
"tag" => "mixed",
"type" => "mixed",
"listen" => "0.0.0.0",
"listen_port" => 1082,
"sniff" => true
];
$parsedData['inbounds'] = $newInbounds;
}
if (isset($parsedData['experimental']['clash_api'])) {
$parsedData['experimental']['clash_api'] = [
"external_ui" => "/etc/neko/ui/",
"external_controller" => "0.0.0.0:9090",
"secret" => "Akun"
];
}
$fileContent = json_encode($parsedData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return $fileContent;
}
function saveSubscriptionContentToYaml($url, $filename) {
global $download_path;
if (pathinfo($filename, PATHINFO_EXTENSION) !== 'json') {
$filename .= '.json';
}
if (strpbrk($filename, "!@#$%^&*()+=[]\\\';,/{}|\":<>?") !== false) {
$message = "文件名包含非法字符,请使用字母、数字、点、下划线或横杠。";
logMessage($message);
return $message;
}
if (!is_dir($download_path)) {
if (!mkdir($download_path, 0755, true)) {
$message = "无法创建目录:$download_path";
logMessage($message);
return $message;
}
}
$output_file = escapeshellarg($download_path . $filename);
$command = "wget -q --no-check-certificate -O $output_file " . escapeshellarg($url);
exec($command, $output, $return_var);
if ($return_var !== 0) {
$message = "wget 错误,无法获取订阅内容。请检查链接是否正确。";
logMessage($message);
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$subscription_data = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
curl_close($ch);
$message = "cURL 错误: $error_msg";
logMessage($message);
return $message;
}
curl_close($ch);
if (empty($subscription_data)) {
$message = "无法获取订阅内容。请检查链接是否正确。";
logMessage($message);
return $message;
}
$transformed_data = transformContent($subscription_data);
$file_path = $download_path . $filename;
$success = file_put_contents($file_path, $transformed_data) !== false;
$message = $success ? "内容已成功保存到:$file_path" : "文件保存失败。";
logMessage($message);
return $message;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$templates = [
'1' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Full_NoAuto.ini?',
'2' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Full_AdblockPlus.ini?',
'3' => 'https://raw.githubusercontent.com/youshandefeiyang/webcdn/main/SONY.ini',
'4' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/default_with_clash_adg.yml?',
'5' => 'https://raw.githubusercontent.com/WC-Dream/ACL4SSR/WD/Clash/config/ACL4SSR_Online_Full_Dream.ini?',
'6' => 'https://raw.githubusercontent.com/WC-Dream/ACL4SSR/WD/Clash/config/ACL4SSR_Mini_Dream.ini?',
'7' => 'https://raw.githubusercontent.com/justdoiting/ClashRule/main/GeneralClashRule.ini?',
'8' => 'https://raw.githubusercontent.com/cutethotw/ClashRule/main/GeneralClashRule.ini?',
'9' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini?',
'10' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_NoAuto.ini?',
'11' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_AdblockPlus.ini?',
'12' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_MultiCountry.ini?',
'13' => 'ttps://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_NoReject.ini?',
'14' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_NoAuto.ini?',
'15' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Full.ini?',
'16' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Full_Google.ini?',
'17' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Full_MultiMode.ini?',
'18' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Full_Netflix.ini?',
'19' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini.ini?',
'20' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_AdblockPlus.ini?',
'21' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_Fallback.ini?',
'22' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_MultiCountry.ini?',
'23' => 'https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_MultiMode.ini?',
'24' => 'https://raw.githubusercontent.com/flyhigherpi/merlinclash_clash_related/master/Rule_config/ZHANG.ini?',
'25' => 'https://raw.githubusercontent.com/xiaoshenxian233/cool/rule/complex.ini?',
'26' => 'https://subweb.s3.fr-par.scw.cloud/RemoteConfig/special/phaors.ini?',
'27' => 'https://raw.githubusercontent.com/flyhigherpi/merlinclash_clash_related/master/Rule_config/ZHANG_Area_Fallback.ini?',
'28' => 'https://raw.githubusercontent.com/flyhigherpi/merlinclash_clash_related/master/Rule_config/ZHANG_Area_Urltest.ini?',
'29' => 'https://raw.githubusercontent.com/flyhigherpi/merlinclash_clash_related/master/Rule_config/ZHANG_Area_NoAuto.ini?',
'30' => 'https://raw.githubusercontent.com/OoHHHHHHH/ini/master/config.ini?',
'31' => 'https://raw.githubusercontent.com/OoHHHHHHH/ini/master/cfw-tap.ini?',
'32' => 'https://raw.githubusercontent.com/lhl77/sub-ini/main/tsutsu-full.ini?',
'33' => 'https://raw.githubusercontent.com/lhl77/sub-ini/main/tsutsu-mini-gfw.ini?',
'34' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/connershua_new.ini?',
'35' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/connershua_backtocn.ini?',
'36' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/lhie1_clash.ini?',
'37' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/lhie1_dler.ini?',
'38' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/ehpo1_main.ini?',
'39' => 'https://raw.nameless13.com/api/public/dl/ROzQqi2S/white.ini?',
'40' => 'https://raw.nameless13.com/api/public/dl/ptLeiO3S/mayinggfw.ini?',
'41' => 'https://raw.nameless13.com/api/public/dl/FWSh3dXz/easy3.ini?',
'42' => 'https://raw.nameless13.com/api/public/dl/L_-vxO7I/youtube.ini?',
'43' => 'https://raw.nameless13.com/api/public/dl/zKF9vFbb/easy.ini?',
'44' => 'https://raw.nameless13.com/api/public/dl/E69bzCaE/easy2.ini?',
'45' => 'https://raw.nameless13.com/api/public/dl/XHr0miMg/ipip.ini?',
'46' => 'https://raw.nameless13.com/api/public/dl/BBnfb5lD/MAYINGVIP.ini?',
'47' => 'https://raw.githubusercontent.com/Mazeorz/airports/master/Clash/Examine.ini?',
'48' => 'https://raw.githubusercontent.com/Mazeorz/airports/master/Clash/Examine_Full.ini?',
'49' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/nzw9314_custom.ini?',
'50' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/maicoo-l_custom.ini?',
'51' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/dlercloud_lige_platinum.ini?',
'52' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/dlercloud_lige_gold.ini?',
'53' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/dlercloud_lige_silver.ini?',
'54' => 'https://unpkg.com/proxy-script/config/Clash/clash.ini?',
'55' => 'https://github.com/UlinoyaPed/ShellClash/raw/master/rules/ShellClash.ini?',
'56' => 'https://gist.github.com/jklolixxs/16964c46bad1821c70fa97109fd6faa2/raw/EXFLUX.ini?',
'57' => 'https://gist.github.com/jklolixxs/32d4e9a1a5d18a92beccf3be434f7966/raw/NaNoport.ini?',
'58' => 'https://gist.github.com/jklolixxs/dfbe0cf71ffc547557395c772836d9a8/raw/CordCloud.ini?',
'59' => 'https://gist.github.com/jklolixxs/e2b0105c8be6023f3941816509a4c453/raw/BigAirport.ini?',
'60' => 'https://gist.github.com/jklolixxs/9f6989137a2cfcc138c6da4bd4e4cbfc/raw/PaoLuCloud.ini?',
'61' => 'https://gist.github.com/jklolixxs/fccb74b6c0018b3ad7b9ed6d327035b3/raw/WaveCloud.ini?',
'62' => 'https://gist.github.com/jklolixxs/bfd5061dceeef85e84401482f5c92e42/raw/JiJi.ini?',
'63' => 'https://gist.github.com/jklolixxs/6ff6e7658033e9b535e24ade072cf374/raw/SJ.ini?',
'64' => 'https://gist.github.com/jklolixxs/24f4f58bb646ee2c625803eb916fe36d/raw/ImmTelecom.ini?',
'65' => 'https://gist.github.com/jklolixxs/b53d315cd1cede23af83322c26ce34ec/raw/AmyTelecom.ini?',
'66' => 'https://subweb.s3.fr-par.scw.cloud/RemoteConfig/customized/convenience.ini?',
'67' => 'https://gist.github.com/jklolixxs/ff8ddbf2526cafa568d064006a7008e7/raw/Miaona.ini?',
'68' => 'https://gist.github.com/jklolixxs/df8fda1aa225db44e70c8ac0978a3da4/raw/Foo&Friends.ini?',
'69' => 'https://gist.github.com/jklolixxs/b1f91606165b1df82e5481b08fd02e00/raw/ABCloud.ini?',
'70' => 'https://raw.githubusercontent.com/SleepyHeeead/subconverter-config/master/remote-config/customized/xianyu.ini?',
'71' => 'https://subweb.oss-cn-hongkong.aliyuncs.com/RemoteConfig/customized/convenience.ini?',
'72' => 'https://raw.githubusercontent.com/Mazeorz/airports/master/Clash/SSRcloud.ini?',
'73' => 'https://raw.githubusercontent.com/Mazetsz/ACL4SSR/master/Clash/config/V2rayPro.ini?',
'74' => 'https://raw.githubusercontent.com/Mazeorz/airports/master/Clash/V2Pro.ini?',
'75' => 'https://raw.githubusercontent.com/Mazeorz/airports/master/Clash/Stitch.ini?',
'76' => 'https://raw.githubusercontent.com/Mazeorz/airports/master/Clash/Stitch-Balance.ini?',
'77' => 'https://raw.githubusercontent.com/SleepyHeeead/subconverter-config/master/remote-config/customized/maying.ini?',
'78' => 'https://subweb.s3.fr-par.scw.cloud/RemoteConfig/customized/ytoo.ini?',
'79' => 'https://raw.nameless13.com/api/public/dl/M-We_Fn7/w8ves.ini?',
'80' => 'https://raw.githubusercontent.com/SleepyHeeead/subconverter-config/master/remote-config/customized/nyancat.ini?',
'81' => 'https://subweb.s3.fr-par.scw.cloud/RemoteConfig/customized/nexitally.ini?',
'82' => 'https://raw.githubusercontent.com/SleepyHeeead/subconverter-config/master/remote-config/customized/socloud.ini?',
'83' => 'https://raw.githubusercontent.com/SleepyHeeead/subconverter-config/master/remote-config/customized/ark.ini?',
'84' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/n3ro_optimized.ini?',
'85' => 'https://gist.githubusercontent.com/tindy2013/1fa08640a9088ac8652dbd40c5d2715b/raw/scholar_optimized.ini?',
'86' => 'https://subweb.s3.fr-par.scw.cloud/RemoteConfig/customized/flower.ini?',
'88' => 'https://raw.githubusercontent.com/SleepyHeeead/subconverter-config/master/remote-config/special/netease.ini?',
'89' => 'https://raw.githubusercontent.com/SleepyHeeead/subconverter-config/master/remote-config/special/basic.ini?'
];
$emoji = isset($_POST['emoji']) ? $_POST['emoji'] === 'true' : true;
$udp = isset($_POST['udp']) ? $_POST['udp'] === 'true' : true;
$xudp = isset($_POST['xudp']) ? $_POST['xudp'] === 'true' : true;
$tfo = isset($_POST['tfo']) ? $_POST['tfo'] === 'true' : true;
$fdn = isset($_POST['fdn']) ? $_POST['fdn'] === 'true' : true;
$sort = isset($_POST['sort']) ? $_POST['sort'] === 'true' : true;
$tls13 = isset($_POST['tls13']) ? $_POST['tls13'] === 'true' : true;
$ipv6 = isset($_POST['ipv6']) ? $_POST['ipv6'] : 'false';
$filename = isset($_POST['filename']) && $_POST['filename'] !== '' ? $_POST['filename'] : 'config.json';
$subscription_url = isset($_POST['subscription_url']) ? $_POST['subscription_url'] : '';
$backend_url = isset($_POST['backend_url']) && $_POST['backend_url'] === 'custom' && !empty($_POST['custom_backend_url'])
? rtrim($_POST['custom_backend_url'], '?') . '?'
: ($_POST['backend_url'] ?? 'https://url.v1.mk/sub?');
$template_key = $_POST['template'] ?? '';
$include = $_POST['include'] ?? '';
$exclude = $_POST['exclude'] ?? '';
$template = $templates[$template_key] ?? '';
$rename = isset($_POST['rename']) ? $_POST['rename'] : '';
if (isset($_POST['action']) && $_POST['action'] === 'generate_subscription') {
$final_url = buildFinalUrl($subscription_url, $template, $include, $exclude, $backend_url, $emoji, $udp, $xudp, $tfo, $ipv6, $rename, $tls13, $fdn, $sort);
if (saveSubscriptionUrlToFile($final_url, $subscription_file)) {
$result = saveSubscriptionContentToYaml($final_url, $filename);
} else {
$result = "保存订阅链接到文件失败。";
}
}
if (isset($result)) {
echo nl2br(htmlspecialchars($result));
}
$download_option = $_POST['download_option'] ?? 'none';
if (isset($_POST['download_action']) && $_POST['download_action'] === 'download_files') {
if ($download_option === 'geoip') {
$geoip_url = "https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db";
$geoip_path = '/www/nekobox/geoip.db';
echo downloadFileWithWget($geoip_url, $geoip_path);
} elseif ($download_option === 'geosite') {
$geosite_url = "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db";
$geosite_path = '/www/nekobox/geosite.db';
echo downloadFileWithWget($geosite_url, $geosite_path);
}
}
}
function downloadFileWithWget($url, $path) {
$command = "wget -q --no-check-certificate -O " . escapeshellarg($path) . " " . escapeshellarg($url);
exec($command, $output, $return_var);
if ($return_var === 0) {
return "文件下载成功: $path<br>";
} else {
return "文件下载失败: $path<br>";
}
}
?>
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['createCronJob'])) {
$cronExpression = trim($_POST['cronExpression']);
if (empty($cronExpression)) {
echo "<div class='alert alert-warning'>Cron 表达式不能为空。</div>";
exit;
}
$cronJob = "$cronExpression /etc/neko/core/update_singbox.sh > /dev/null 2>&1";
exec("crontab -l | grep -v '/etc/neko/core/update_singbox.sh' | crontab -");
exec("(crontab -l; echo '$cronJob') | crontab -");
echo "<div class='alert alert-success'>Cron 任务已成功添加或更新!</div>";
}
}
?>
<?php
$shellScriptPath = '/etc/neko/core/update_singbox.sh';
$LOG_FILE = '/etc/neko/tmp/log.txt';
$CONFIG_FILE = '/etc/neko/config/config.json';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (isset($_POST['createShellScript'])) {
$shellScriptContent = <<<EOL
#!/bin/sh
LOG_FILE="/etc/neko/tmp/log.txt"
LINK_FILE="/etc/neko/tmp/singbox.txt"
CONFIG_FILE="/etc/neko/config/config.json"
log() {
echo "[ \$(date +'%H:%M:%S') ] \$1" >> "\$LOG_FILE"
}
log "启动更新脚本..."
log "尝试读取订阅链接文件:\$LINK_FILE"
if [ ! -f "\$LINK_FILE" ]; then
log "错误:文件 \$LINK_FILE 不存在。"
exit 1
fi
SUBSCRIBE_URL=\$(awk 'NR==1 {print \$0}' "\$LINK_FILE" | tr -d '\\n\\r' | xargs)
if [ -z "\$SUBSCRIBE_URL" ]; then
log "错误:订阅链接为空或提取失败。"
exit 1
fi
log "使用的订阅链接:\$SUBSCRIBE_URL"
log "尝试下载并更新配置文件..."
wget -q -O "\$CONFIG_FILE" "\$SUBSCRIBE_URL" >> "\$LOG_FILE" 2>&1
if [ \$? -eq 0 ]; then
log "配置文件更新成功,保存路径:\$CONFIG_FILE"
else
log "配置文件更新失败,请检查链接或网络。"
exit 1
fi
jq '.inbounds = [
{
"domain_strategy": "prefer_ipv4",
"listen": "127.0.0.1",
"listen_port": 2334,
"sniff": true,
"sniff_override_destination": true,
"tag": "mixed-in",
"type": "mixed",
"users": []
},
{
"tag": "tun",
"type": "tun",
"address": [
"172.19.0.1/30",
"fdfe:dcba:9876::1/126"
],
"route_address": [
"0.0.0.0/1",
"128.0.0.0/1",
"::/1",
"8000::/1"
],
"route_exclude_address": [
"192.168.0.0/16",
"fc00::/7"
],
"stack": "system",
"auto_route": true,
"strict_route": true,
"sniff": true,
"platform": {
"http_proxy": {
"enabled": true,
"server": "0.0.0.0",
"server_port": 1082
}
}
},
{
"tag": "mixed",
"type": "mixed",
"listen": "0.0.0.0",
"listen_port": 1082,
"sniff": true
}
]' "\$CONFIG_FILE" > /tmp/config_temp.json && mv /tmp/config_temp.json "\$CONFIG_FILE"
jq '.experimental.clash_api = {
"external_ui": "/etc/neko/ui/",
"external_controller": "0.0.0.0:9090",
"secret": "Akun"
}' "\$CONFIG_FILE" > /tmp/config_temp.json && mv /tmp/config_temp.json "\$CONFIG_FILE"
if [ \$? -eq 0 ]; then
log "配置文件修改已成功完成。"
else
log "错误:配置文件修改失败。"
exit 1
fi
EOL;
if (file_put_contents($shellScriptPath, $shellScriptContent) !== false) {
chmod($shellScriptPath, 0755);
echo "<div class='alert alert-success'>Shell 脚本已成功创建!路径: $shellScriptPath</div>";
} else {
echo "<div class='alert alert-danger'>无法创建 Shell 脚本,请检查权限。</div>";
}
}
}
?>
<!doctype html>
<html lang="en" data-bs-theme="<?php echo substr($neko_theme, 0, -4) ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>singbox - Nekobox</title>
<link rel="icon" href="./assets/img/nekobox.png">
<link href="./assets/css/bootstrap.min.css" rel="stylesheet">
<link href="./assets/css/custom.css" rel="stylesheet">
<link href="./assets/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="./assets/theme/<?php echo $neko_theme ?>" rel="stylesheet">
<script type="text/javascript" src="./assets/js/bootstrap.min.js"></script>
<script type="text/javascript" src="./assets/js/feather.min.js"></script>
<script type="text/javascript" src="./assets/bootstrap/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="./assets/js/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="./assets/js/neko.js"></script>
<?php include './ping.php'; ?>
</head>
<body>
<style>
.custom-padding {
padding-left: 5ch;
padding-right: 5ch;
}
@media (max-width: 767px) {
.custom-padding {
padding-left: 3ch;
padding-right: 3ch;
}
@media (max-width: 767px) {
.row a {
font-size: 9px;
}
}
.table-responsive {
width: 100%;
}
</style>
<div class="container-sm container-bg callout border border-3 rounded-4 col-11">
<div class="row">
<a href="./index.php" class="col btn btn-lg text-nowrap"><i class="bi bi-house-door"></i> 首页</a>
<a href="./mihomo_manager.php" class="col btn btn-lg text-nowrap"><i class="bi bi-folder"></i> 文件管理</a>
<a href="./singbox.php" class="col btn btn-lg text-nowrap"><i class="bi bi-shop"></i> 模板 一</a>
<a href="./subscription.php" class="col btn btn-lg text-nowrap"><i class="bi bi-bank"></i> 模板 二</a>
<a href="./mihomo.php" class="col btn btn-lg text-nowrap"><i class="bi bi-building"></i> 模板 三</a>
<h1 class="text-center p-2" style="margin-top: 2rem; margin-bottom: 1rem;">Sing-box 转换模板 二</h1>
<div class="col-12 custom-padding">
<div class="form-section">
<form method="post">
<div class="mb-3">
<label for="subscription_url" class="form-label">输入订阅链接</label>
<input type="text" class="form-control" id="subscription_url" name="subscription_url"
value="<?php echo htmlspecialchars($current_subscription_url); ?>"placeholder="支持各种订阅链接或单节点链接,多个链接用 | 分隔" required>
</div>
<div class="mb-3">
<label for="filename" class="form-label">自定义文件名 (默认: config.json)</label>
<input type="text" class="form-control" id="filename" name="filename"
value="<?php echo htmlspecialchars(isset($_POST['filename']) ? $_POST['filename'] : ''); ?>"
placeholder="config.json">
</div>
<div class="mb-3">
<label for="backend_url" class="form-label">选择后端地址</label>
<select class="form-select" id="backend_url" name="backend_url" required>
<option value="https://url.v1.mk/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://url.v1.mk/sub?' ? 'selected' : ''; ?>>
肥羊增强型后端【vless reality+hy1+hy2】
</option>
<option value="https://sub.d1.mk/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://sub.d1.mk/sub?' ? 'selected' : ''; ?>>
肥羊备用后端【vless reality+hy1+hy2】
</option>
<option value="https://sub.xeton.dev/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://sub.xeton.dev/sub?' ? 'selected' : ''; ?>>
subconverter作者提供
</option>
<option value="https://www.tline.website/sub/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://www.tline.website/sub/sub?' ? 'selected' : ''; ?>>
tline.website
</option>
<option value="https://api.dler.io/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://api.dler.io/sub?' ? 'selected' : ''; ?>>
api.dler.io
</option>
<option value="https://v.id9.cc/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://v.id9.cc/sub?' ? 'selected' : ''; ?>>
v.id9.cc(品云提供)
</option>
<option value="https://sub.id9.cc/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://sub.id9.cc/sub?' ? 'selected' : ''; ?>>
sub.id9.cc
</option>
<option value="https://api.wcc.best/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://api.wcc.best/sub?' ? 'selected' : ''; ?>>
api.wcc.best
</option>
<option value="https://yun-api.subcloud.xyz/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://yun-api.subcloud.xyz/sub?' ? 'selected' : ''; ?>>
subcloud.xyz
</option>
<option value="https://sub.maoxiongnet.com/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'https://sub.maoxiongnet.com/sub?' ? 'selected' : ''; ?>>
sub.maoxiongnet.com(猫熊提供)
</option>
<option value="http://localhost:25500/sub?" <?php echo ($_POST['backend_url'] ?? '') === 'http://localhost:25500/sub?' ? 'selected' : ''; ?>>
localhost:25500 本地版
</option>
<option value="custom" <?php echo ($_POST['backend_url'] ?? '') === 'custom' ? 'selected' : ''; ?>>
自定义后端地址
</option>
</select>
</div>
<div class="mb-3" id="custom_backend_url_input" style="display: none;">
<label for="custom_backend_url" class="form-label">请输入自定义后端地址</label>
<input type="text" class="form-control" id="custom_backend_url" name="custom_backend_url" value="<?php echo htmlspecialchars($_POST['custom_backend_url'] ?? '') . (empty($_POST['custom_backend_url']) ? '' : '?'); ?>" />
</div>
<div class="mb-3">
<label for="template" class="form-label">选择订阅转换模板</label>
<select class="form-select" id="template" name="template" required>
<optgroup label="通用" style="color: #28a745; font-size: 20px;">
<option value="1" <?php echo ($_POST['template'] ?? '') === '1' ? 'selected' : ''; ?>>默认</option>
<option value="2" <?php echo ($_POST['template'] ?? '') === '2' ? 'selected' : ''; ?>>默认(自动测速)</option>
<option value="3" <?php echo ($_POST['template'] ?? '') === '3' ? 'selected' : ''; ?>>默认(索尼电视专用)</option>
<option value="4" <?php echo ($_POST['template'] ?? '') === '4' ? 'selected' : ''; ?>>默认(附带用于 Clash 的 AdGuard DNS</option>
<option value="5" <?php echo ($_POST['template'] ?? '') === '5' ? 'selected' : ''; ?>>ACL_全分组 Dream修改版</option>
<option value="6" <?php echo ($_POST['template'] ?? '') === '6' ? 'selected' : ''; ?>>ACL_精简分组 Dream修改版</option>
<option value="7" <?php echo ($_POST['template'] ?? '') === '7' ? 'selected' : ''; ?>>emby-TikTok-流媒体分组-去广告加强版</option>
<option value="8" <?php echo ($_POST['template'] ?? '') === '8' ? 'selected' : ''; ?>>流媒体通用分组</option>
</optgroup>
<optgroup label="ACL规则" style="color: #fd7e14; font-size: 20px;">
<option value="9" <?php echo ($_POST['template'] ?? '') === '9' ? 'selected' : ''; ?>>ACL_默认版</option>
<option value="10" <?php echo ($_POST['template'] ?? '') === '10' ? 'selected' : ''; ?>>ACL_无测速版</option>
<option value="11" <?php echo ($_POST['template'] ?? '') === '11' ? 'selected' : ''; ?>>ACL_去广告版</option>
<option value="12" <?php echo ($_POST['template'] ?? '') === '12' ? 'selected' : ''; ?>>ACL_多国家版</option>
<option value="13" <?php echo ($_POST['template'] ?? '') === '13' ? 'selected' : ''; ?>>ACL_无Reject版</option>
<option value="14" <?php echo ($_POST['template'] ?? '') === '14' ? 'selected' : ''; ?>>ACL_无测速精简版</option>
<option value="15" <?php echo ($_POST['template'] ?? '') === '15' ? 'selected' : ''; ?>>ACL_全分组版</option>
<option value="16" <?php echo ($_POST['template'] ?? '') === '16' ? 'selected' : ''; ?>>ACL_全分组谷歌版</option>
<option value="17" <?php echo ($_POST['template'] ?? '') === '17' ? 'selected' : ''; ?>>ACL_全分组多模式版</option>
<option value="18" <?php echo ($_POST['template'] ?? '') === '18' ? 'selected' : ''; ?>>ACL_全分组奈飞版</option>
<option value="19" <?php echo ($_POST['template'] ?? '') === '19' ? 'selected' : ''; ?>>ACL_精简版</option>
<option value="20" <?php echo ($_POST['template'] ?? '') === '20' ? 'selected' : ''; ?>>ACL_去广告精简版</option>
<option value="21" <?php echo ($_POST['template'] ?? '') === '21' ? 'selected' : ''; ?>>ACL_Fallback精简版</option>
<option value="22" <?php echo ($_POST['template'] ?? '') === '22' ? 'selected' : ''; ?>>ACL_多国家精简版</option>
<option value="23" <?php echo ($_POST['template'] ?? '') === '23' ? 'selected' : ''; ?>>ACL_多模式精简版</option>
</optgroup>
<optgroup label="全网搜集规则" style="color: #6f42c1; font-size: 20px;">
<option value="24" <?php echo ($_POST['template'] ?? '') === '24' ? 'selected' : ''; ?>>常规规则</option>
<option value="25" <?php echo ($_POST['template'] ?? '') === '25' ? 'selected' : ''; ?>>酷酷自用</option>
<option value="26" <?php echo ($_POST['template'] ?? '') === '26' ? 'selected' : ''; ?>>PharosPro无测速</option>
<option value="27" <?php echo ($_POST['template'] ?? '') === '27' ? 'selected' : ''; ?>>分区域故障转移</option>
<option value="28" <?php echo ($_POST['template'] ?? '') === '28' ? 'selected' : ''; ?>>分区域自动测速</option>
<option value="29" <?php echo ($_POST['template'] ?? '') === '29' ? 'selected' : ''; ?>>分区域无自动测速</option>
<option value="30" <?php echo ($_POST['template'] ?? '') === '30' ? 'selected' : ''; ?>>OoHHHHHHH</option>
<option value="31" <?php echo ($_POST['template'] ?? '') === '31' ? 'selected' : ''; ?>>CFW-TAP</option>
<option value="32" <?php echo ($_POST['template'] ?? '') === '32' ? 'selected' : ''; ?>>lhl77全分组定期更新</option>
<option value="33" <?php echo ($_POST['template'] ?? '') === '33' ? 'selected' : ''; ?>>lhl77简易版定期更新</option>
<option value="34" <?php echo ($_POST['template'] ?? '') === '34' ? 'selected' : ''; ?>>ConnersHua 神机规则 Outbound</option>
<option value="35" <?php echo ($_POST['template'] ?? '') === '35' ? 'selected' : ''; ?>>ConnersHua 神机规则 Inbound 回国专用</option>
<option value="36" <?php echo ($_POST['template'] ?? '') === '36' ? 'selected' : ''; ?>>lhie1 洞主规则(使用 Clash 分组规则)</option>
<option value="37" <?php echo ($_POST['template'] ?? '') === '37' ? 'selected' : ''; ?>>lhie1 洞主规则完整版</option>
<option value="38" <?php echo ($_POST['template'] ?? '') === '38' ? 'selected' : ''; ?>>eHpo1 规则</option>
<option value="39" <?php echo ($_POST['template'] ?? '') === '39' ? 'selected' : ''; ?>>多策略组默认白名单模式</option>
<option value="40" <?php echo ($_POST['template'] ?? '') === '40' ? 'selected' : ''; ?>>多策略组可以有效减少审计触发</option>
<option value="41" <?php echo ($_POST['template'] ?? '') === '41' ? 'selected' : ''; ?>>精简策略默认白名单</option>
<option value="42" <?php echo ($_POST['template'] ?? '') === '42' ? 'selected' : ''; ?>>多策略增加SMTP策略</option>
<option value="43" <?php echo ($_POST['template'] ?? '') === '43' ? 'selected' : ''; ?>>无策略入门推荐</option>
<option value="44" <?php echo ($_POST['template'] ?? '') === '44' ? 'selected' : ''; ?>>无策略入门推荐国家分组</option>
<option value="45" <?php echo ($_POST['template'] ?? '') === '45' ? 'selected' : ''; ?>>无策略仅IPIP CN + Final</option>
<option value="46" <?php echo ($_POST['template'] ?? '') === '46' ? 'selected' : ''; ?>>无策略魅影vip分组</option>
<option value="47" <?php echo ($_POST['template'] ?? '') === '47' ? 'selected' : ''; ?>>品云专属配置(仅香港区域分组)</option>
<option value="48" <?php echo ($_POST['template'] ?? '') === '48' ? 'selected' : ''; ?>>品云专属配置(全地域分组)</option>
<option value="49" <?php echo ($_POST['template'] ?? '') === '49' ? 'selected' : ''; ?>>nzw9314 规则</option>
<option value="50" <?php echo ($_POST['template'] ?? '') === '50' ? 'selected' : ''; ?>>maicoo-l 规则</option>
<option value="51" <?php echo ($_POST['template'] ?? '') === '51' ? 'selected' : ''; ?>>DlerCloud Platinum 李哥定制规则</option>
<option value="52" <?php echo ($_POST['template'] ?? '') === '52' ? 'selected' : ''; ?>>DlerCloud Gold 李哥定制规则</option>
<option value="53" <?php echo ($_POST['template'] ?? '') === '53' ? 'selected' : ''; ?>>DlerCloud Silver 李哥定制规则</option>
<option value="54" <?php echo ($_POST['template'] ?? '') === '54' ? 'selected' : ''; ?>>ProxyStorage自用</option>
<option value="55" <?php echo ($_POST['template'] ?? '') === '55' ? 'selected' : ''; ?>>ShellClash修改版规则 (by UlinoyaPed)</option>
</optgroup>
<optgroup label="各大机场规则" style="color: #007bff; font-size: 20px;">
<option value="56" <?php echo ($_POST['template'] ?? '') === '56' ? 'selected' : ''; ?>>EXFLUX</option>
<option value="57" <?php echo ($_POST['template'] ?? '') === '57' ? 'selected' : ''; ?>>NaNoport</option>
<option value="58" <?php echo ($_POST['template'] ?? '') === '58' ? 'selected' : ''; ?>>CordCloud</option>
<option value="59" <?php echo ($_POST['template'] ?? '') === '59' ? 'selected' : ''; ?>>BigAirport</option>
<option value="60" <?php echo ($_POST['template'] ?? '') === '60' ? 'selected' : ''; ?>>跑路云</option>
<option value="61" <?php echo ($_POST['template'] ?? '') === '61' ? 'selected' : ''; ?>>WaveCloud</option>
<option value="62" <?php echo ($_POST['template'] ?? '') === '62' ? 'selected' : ''; ?>>几鸡</option>
<option value="63" <?php echo ($_POST['template'] ?? '') === '63' ? 'selected' : ''; ?>>四季加速</option>
<option value="64" <?php echo ($_POST['template'] ?? '') === '64' ? 'selected' : ''; ?>>ImmTelecom</option>
<option value="65" <?php echo ($_POST['template'] ?? '') === '65' ? 'selected' : ''; ?>>AmyTelecom</option>
<option value="66" <?php echo ($_POST['template'] ?? '') === '66' ? 'selected' : ''; ?>>LinkCube</option>
<option value="67" <?php echo ($_POST['template'] ?? '') === '67' ? 'selected' : ''; ?>>Miaona</option>
<option value="68" <?php echo ($_POST['template'] ?? '') === '68' ? 'selected' : ''; ?>>Foo&Friends</option>
<option value="69" <?php echo ($_POST['template'] ?? '') === '69' ? 'selected' : ''; ?>>ABCloud</option>
<option value="70" <?php echo ($_POST['template'] ?? '') === '70' ? 'selected' : ''; ?>>咸鱼</option>
<option value="71" <?php echo ($_POST['template'] ?? '') === '71' ? 'selected' : ''; ?>>便利店</option>
<option value="72" <?php echo ($_POST['template'] ?? '') === '72' ? 'selected' : ''; ?>>CNIX</option>
<option value="73" <?php echo ($_POST['template'] ?? '') === '73' ? 'selected' : ''; ?>>Nirvana</option>
<option value="74" <?php echo ($_POST['template'] ?? '') === '74' ? 'selected' : ''; ?>>V2Pro</option>
<option value="75" <?php echo ($_POST['template'] ?? '') === '75' ? 'selected' : ''; ?>>史迪仔-自动测速</option>
<option value="76" <?php echo ($_POST['template'] ?? '') === '76' ? 'selected' : ''; ?>>史迪仔-负载均衡</option>
<option value="77" <?php echo ($_POST['template'] ?? '') === '77' ? 'selected' : ''; ?>>Maying</option>
<option value="78" <?php echo ($_POST['template'] ?? '') === '78' ? 'selected' : ''; ?>>Ytoo</option>
<option value="79" <?php echo ($_POST['template'] ?? '') === '79' ? 'selected' : ''; ?>>w8ves</option>
<option value="80" <?php echo ($_POST['template'] ?? '') === '80' ? 'selected' : ''; ?>>NyanCAT</option>
<option value="81" <?php echo ($_POST['template'] ?? '') === '81' ? 'selected' : ''; ?>>Nexitally</option>
<option value="82" <?php echo ($_POST['template'] ?? '') === '82' ? 'selected' : ''; ?>>SoCloud</option>
<option value="83" <?php echo ($_POST['template'] ?? '') === '83' ? 'selected' : ''; ?>>ARK</option>
<option value="84" <?php echo ($_POST['template'] ?? '') === '84' ? 'selected' : ''; ?>>N3RO</option>
<option value="85" <?php echo ($_POST['template'] ?? '') === '85' ? 'selected' : ''; ?>>Scholar</option>
<option value="86" <?php echo ($_POST['template'] ?? '') === '86' ? 'selected' : ''; ?>>Flowercloud</option>
</optgroup>
<optgroup label="特殊" style="color: #ff0000; font-size: 20px;">
<option value="87" <?php echo ($_POST['template'] ?? '') === '87' ? 'selected' : ''; ?>>NeteaseUnblock</option>
<option value="88" <?php echo ($_POST['template'] ?? '') === '88' ? 'selected' : ''; ?>>Basic</option>
</optgroup>
</select>
</div>
<div class="mb-3">
<label class="form-label">选择额外配置选项</label>
<div class="d-flex flex-wrap align-items-center">
<div class="form-check me-3">
<input type="checkbox" class="form-check-input" id="emoji" name="emoji" value="true"
<?php echo isset($_POST['emoji']) && $_POST['emoji'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="emoji">启用 Emoji</label>
</div>
<div class="form-check me-3">
<input type="checkbox" class="form-check-input" id="udp" name="udp" value="true"
<?php echo isset($_POST['udp']) && $_POST['udp'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="udp">启用 UDP</label>
</div>
<div class="form-check me-3">
<input type="checkbox" class="form-check-input" id="xudp" name="xudp" value="true"
<?php echo isset($_POST['xudp']) && $_POST['xudp'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="xudp">启用 XUDP</label>
</div>
<div class="form-check me-3">
<input type="checkbox" class="form-check-input" id="tfo" name="tfo" value="true"
<?php echo isset($_POST['tfo']) && $_POST['tfo'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="tfo">启用 TFO</label>
</div>
<div class="form-check me-3">
<input type="checkbox" class="form-check-input" id="fdn" name="fdn" value="true"
<?php echo isset($_POST['fdn']) && $_POST['fdn'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="tls13">启用 FDN</label>
</div>
<div class="form-check me-3">
<input type="checkbox" class="form-check-input" id="sort" name="sort" value="true"
<?php echo isset($_POST['sort']) && $_POST['sort'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="sort">启用 SORT</label>
</div>
<div class="form-check me-3">
<input type="checkbox" class="form-check-input" id="tls13" name="tls13" value="true"
<?php echo isset($_POST['tls13']) && $_POST['tls13'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="tls13">启用 TLS_1.3</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="ipv6" name="ipv6" value="true"
<?php echo isset($_POST['ipv6']) && $_POST['ipv6'] == 'true' ? 'checked' : ''; ?>>
<label class="form-check-label" for="ipv6">启用 IPv6</label>
</div>
</div>
</div>
<div class="mb-3">
<label for="include" class="form-label">包含节点 (可选)</label>
<input type="text" class="form-control" id="include" name="include"
value="<?php echo htmlspecialchars($_POST['include'] ?? ''); ?>" placeholder="要保留的节点,支持正则 | 分隔">
</div>
<div class="mb-3">
<label for="exclude" class="form-label">排除节点 (可选)</label>
<input type="text" class="form-control" id="exclude" name="exclude"
value="<?php echo htmlspecialchars($_POST['exclude'] ?? ''); ?>" placeholder="要排除的节点,支持正则 | 分隔">
</div>
<div class="mb-3">
<label for="rename" class="form-label">节点命名</label>
<input type="text" class="form-control" id="rename" name="rename"
value="<?php echo htmlspecialchars(isset($_POST['rename']) ? $_POST['rename'] : ''); ?>"
placeholder="输入重命名内容(举例:`a@b``1@2`|符可用\转义)">
</div>
<div class="mb-3">
<label class="form-label" for="download_option">选择要下载的数据库</label>
<select class="form-select" id="download_option" name="download_option">
<option value="geoip" <?php echo isset($_POST['download_option']) && $_POST['download_option'] === 'geoip' ? 'selected' : ''; ?>>GeoIP 数据库 (geoip.db)</option>
<option value="geosite" <?php echo isset($_POST['download_option']) && $_POST['download_option'] === 'geosite' ? 'selected' : ''; ?>>Geosite 数据库 (geosite.db)</option>
</select>
</div>
<button type="submit" class="btn btn-primary col mx-2" name="action" value="generate_subscription"><i class="bi bi-file-earmark-text"></i> 生成配置文件</button>
<button type="submit" class="btn btn-success" name="download_action" value="download_files"><i class="bi bi-download"></i> 下载数据库</button>
</form>
</div>
</div>
<div class="container custom-padding">
<form method="post">
<h5 style="margin-top: 20px;">定时任务</h5>
<button type="button" class="btn btn-primary mx-2" data-bs-toggle="modal" data-bs-target="#cronModal"><i class="bi bi-clock"></i> 设置定时任务</button>
<button type="submit" name="createShellScript" value="true" class="btn btn-success"><i class="bi bi-terminal"></i> 生成更新脚本</button>
</form>
</div>
<div class="modal fade" id="cronModal" tabindex="-1" aria-labelledby="cronModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="cronModalLabel">设置 Cron 计划任务</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form method="POST">
<div class="mb-3">
<label for="cronExpression" class="form-label">Cron 表达式</label>
<input type="text" class="form-control" id="cronExpression" name="cronExpression" value="0 2 * * *" required>
</div>
<div class="alert alert-info">
<strong>提示:</strong> Cron 表达式格式:
<ul>
<li><code>分钟 小时 日 月 星期</code></li>
<li>示例: 每天凌晨 2 点: <code>0 2 * * *</code></li>
<li>每周一凌晨 3 点: <code>0 3 * * 1</code></li>
<li>工作日(周一至周五)的上午 9 点: <code>0 9 * * 1-5</code></li>
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" name="createCronJob" class="btn btn-primary">保存</button>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="help mt-4 custom-padding">
<strong>1. 对于首次使用 Sing-box 的用户,必须将核心更新至版本 v1.10.0 或更高版本。确保将出站和入站/转发防火墙规则都设置为“接受”并启用它们。<p>
<p style="color: red;">注意:在线订阅转换存在隐私泄露风险,请确保使用 Sing-box 的通道一版本,通道二版本不支持此功能。同时,需要下载 geoip 和 geosite 文件以确保正常使用。</p>
<p>订阅转换由肥羊提供</p>
<a href="https://github.com/youshandefeiyang/sub-web-modify" target="_blank" class="btn btn-primary" style="color: white;">
<i data-feather="github"></i> 点击访问
</a>
</div>
<div class="result mt-4 custom-padding">
<?php echo nl2br(htmlspecialchars($result)); ?>
</div>
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
const formInputs = [
document.getElementById('subscription_url'),
document.getElementById('filename'),
document.getElementById('backend_url'),
document.getElementById('template'),
document.getElementById('include'),
document.getElementById('exclude'),
document.getElementById('cron_time'),
document.getElementById('emoji'),
document.getElementById('udp'),
document.getElementById('xudp'),
document.getElementById('ipv6'),
document.getElementById('sort'),
document.getElementById('fdn'),
document.getElementById('tls13'),
document.getElementById('rename'),
document.getElementById('custom_backend_url'),
document.getElementById('tfo')
];
formInputs.forEach(input => {
if (input) {
if (input.type === 'checkbox') {
input.checked = localStorage.getItem(input.id) === 'true';
} else {
input.value = localStorage.getItem(input.id) || input.value;
}
}
});
function saveSelections() {
formInputs.forEach(input => {
if (input) {
if (input.type === 'checkbox') {
localStorage.setItem(input.id, input.checked);
} else {
localStorage.setItem(input.id, input.value);
}
}
});
}
document.querySelectorAll('form').forEach(form => {
form.addEventListener('submit', saveSelections);
});
formInputs.forEach(input => {
if (input) {
input.addEventListener('change', saveSelections);
}
});
toggleCustomBackendInput();
var backendSelect = document.getElementById('backend_url');
backendSelect.addEventListener('change', toggleCustomBackendInput);
});
function toggleCustomBackendInput() {
var backendSelect = document.getElementById('backend_url');
var customInput = document.getElementById('custom_backend_url_input');
if (backendSelect.value === 'custom') {
customInput.style.display = 'block';
} else {
customInput.style.display = 'none';
}
}
</script>
<footer class="text-center">
<p><?php echo $footer ?></p>
</footer>