update 2024-12-10 16:28:20

This commit is contained in:
kenzok8 2024-12-10 16:28:20 +08:00
parent 90365f95f8
commit 18da74527c
14 changed files with 101 additions and 215 deletions

View File

@ -10,14 +10,14 @@
var conf = 'dnsproxy';
var instance = 'dnsproxy';
var callServiceList = rpc.declare({
const callServiceList = rpc.declare({
object: 'service',
method: 'list',
params: ['name'],
expect: { '': {} }
});
var callHostHints = rpc.declare({
const callHostHints = rpc.declare({
object: 'luci-rpc',
method: 'getHostHints',
expect: { '': {} }
@ -60,7 +60,7 @@ return view.extend({
var isRunning = res[0],
hosts = res[1];
var m, s, o, ss, so;
let m, s, o, ss, so;
m = new form.Map('dnsproxy', _('DNS Proxy'));

View File

@ -352,7 +352,7 @@ return baseclass.extend({
},
getFeatures: function() {
var callGetFeatures = rpc.declare({
const callGetFeatures = rpc.declare({
object: 'luci.fchomo',
method: 'get_features',
expect: { '': {} }
@ -363,7 +363,7 @@ return baseclass.extend({
getServiceStatus: function(instance) {
var conf = 'fchomo';
var callServiceList = rpc.declare({
const callServiceList = rpc.declare({
object: 'service',
method: 'list',
params: ['name'],
@ -381,7 +381,7 @@ return baseclass.extend({
},
getClashAPI: function(instance) {
var callGetClashAPI = rpc.declare({
const callGetClashAPI = rpc.declare({
object: 'luci.fchomo',
method: 'get_clash_api',
params: ['instance'],
@ -798,7 +798,7 @@ return baseclass.extend({
},
lsDir: function(type) {
var callLsDir = rpc.declare({
const callLsDir = rpc.declare({
object: 'luci.fchomo',
method: 'dir_ls',
params: ['type'],
@ -814,7 +814,7 @@ return baseclass.extend({
},
readFile: function(type, filename) {
var callReadFile = rpc.declare({
const callReadFile = rpc.declare({
object: 'luci.fchomo',
method: 'file_read',
params: ['type', 'filename'],
@ -830,7 +830,7 @@ return baseclass.extend({
},
writeFile: function(type, filename, content) {
var callWriteFile = rpc.declare({
const callWriteFile = rpc.declare({
object: 'luci.fchomo',
method: 'file_write',
params: ['type', 'filename', 'content'],
@ -846,7 +846,7 @@ return baseclass.extend({
},
downloadFile: function(type, filename, url, header) {
var callDownloadFile = rpc.declare({
const callDownloadFile = rpc.declare({
object: 'luci.fchomo',
method: 'file_download',
params: ['type', 'filename', 'url', 'header'],
@ -862,7 +862,7 @@ return baseclass.extend({
},
removeFile: function(type, filename) {
var callRemoveFile = rpc.declare({
const callRemoveFile = rpc.declare({
object: 'luci.fchomo',
method: 'file_remove',
params: ['type', 'filename'],
@ -879,7 +879,7 @@ return baseclass.extend({
// thanks to homeproxy
uploadCertificate: function(type, filename, ev) {
var callWriteCertificate = rpc.declare({
const callWriteCertificate = rpc.declare({
object: 'luci.fchomo',
method: 'certificate_write',
params: ['filename'],
@ -898,7 +898,7 @@ return baseclass.extend({
.catch((e) => { ui.addNotification(null, E('p', e.message)) });
},
uploadInitialPack: function(ev, section_id) {
var callWriteInitialPack = rpc.declare({
const callWriteInitialPack = rpc.declare({
object: 'luci.fchomo',
method: 'initialpack_write',
expect: { '': {} }

View File

@ -421,7 +421,7 @@ return view.extend({
render: function(data) {
var dashboard_repo = uci.get(data[0], 'api', 'dashboard_repo');
var m, s, o, ss, so;
let m, s, o, ss, so;
m = new form.Map('fchomo', _('Mihomo client'));

View File

@ -11,14 +11,14 @@
'require tools.firewall as fwtool';
'require tools.widgets as widgets';
var callResVersion = rpc.declare({
const callResVersion = rpc.declare({
object: 'luci.fchomo',
method: 'resources_get_version',
params: ['type', 'repo'],
expect: { '': {} }
});
var callCrondSet = rpc.declare({
const callCrondSet = rpc.declare({
object: 'luci.fchomo',
method: 'crond_set',
params: ['type', 'expr'],
@ -26,7 +26,7 @@ var callCrondSet = rpc.declare({
});
function handleResUpdate(type, repo) {
var callResUpdate = rpc.declare({
const callResUpdate = rpc.declare({
object: 'luci.fchomo',
method: 'resources_update',
params: ['type', 'repo'],
@ -122,7 +122,7 @@ return view.extend({
var dashboard_repo = uci.get(data[0], 'api', 'dashboard_repo');
var m, s, o, ss, so;
let m, s, o, ss, so;
m = new form.Map('fchomo', _('FullCombo Mihomo'),
'<img src="' + hm.sharktaikogif + '" title="Ciallo(∠・ω< )⌒☆" height="52"></img>');
@ -169,7 +169,7 @@ return view.extend({
so = ss.option(form.DummyValue, '_conn_check', _('Connection check'));
so.cfgvalue = function() {
var callConnStat = rpc.declare({
const callConnStat = rpc.declare({
object: 'luci.fchomo',
method: 'connection_check',
params: ['url'],

View File

@ -26,7 +26,7 @@ var css = ' \
var hm_dir = '/var/run/fchomo';
function getRuntimeLog(name, filename) {
var callLogClean = rpc.declare({
const callLogClean = rpc.declare({
object: 'luci.fchomo',
method: 'log_clean',
params: ['type'],
@ -87,7 +87,7 @@ function getRuntimeLog(name, filename) {
return view.extend({
render: function(data) {
var m, s, o;
let m, s, o;
m = new form.Map('fchomo');

View File

@ -15,7 +15,7 @@ return view.extend({
},
render: function(data) {
var m, s, o, ss, so;
let m, s, o, ss, so;
m = new form.Map('fchomo', _('Edit node'));

View File

@ -81,7 +81,7 @@ return view.extend({
},
render: function(data) {
var m, s, o;
let m, s, o;
m = new form.Map('fchomo', _('Edit ruleset'));

View File

@ -53,7 +53,7 @@ return view.extend({
var dashboard_repo = uci.get(data[0], 'api', 'dashboard_repo'),
features = data[1];
var m, s, o;
let m, s, o;
m = new form.Map('fchomo', _('Mihomo server'),
_('When used as a server, HomeProxy is a better choice.'));

View File

@ -3,7 +3,7 @@ ob_start();
include './cfg.php';
date_default_timezone_set('Asia/Shanghai');
$dataFilePath = '/tmp/subscription_data.txt';
$dataFilePath = '/etc/neko/subscription_data.txt';
$lastSubscribeUrl = '';
if (file_exists($dataFilePath)) {
@ -53,7 +53,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['setCron'])) {
<?php
$shellScriptPath = '/etc/neko/core/update_subscription.sh';
$DATA_FILE = '/tmp/subscription_data.txt';
$DATA_FILE = '/etc/neko/subscription_data.txt';
$LOG_FILE = '/tmp/update_subscription.log';
$SUBSCRIBE_URL = '';
@ -73,7 +73,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$shellScriptContent = <<<EOL
#!/bin/sh
DATA_FILE="/tmp/subscription_data.txt"
DATA_FILE="/etc/neko/subscription_data.txt"
CONFIG_DIR="/etc/neko/config"
LOG_FILE="/tmp/update_subscription.log"
TEMPLATE_URL="https://raw.githubusercontent.com/Thaolga/Rules/main/Clash/json/config_8.json"
@ -266,7 +266,7 @@ EOL;
</div>
</div>
<?php
$dataFilePath = '/tmp/subscription_data.txt';
$dataFilePath = '/etc/neko/subscription_data.txt';
$configFilePath = '/etc/neko/config/sing-box.json';
$downloadedContent = '';
@ -314,7 +314,7 @@ EOL;
}
$completeSubscribeUrl = "https://sing-box-subscribe-doraemon.vercel.app/config/{$subscribeUrlEncoded}&file={$templateUrlEncoded}";
$tempFilePath = '/tmp/' . $customFileName;
$tempFilePath = '/etc/neko/' . $customFileName;
$logMessages = [];
$command = "wget -O " . escapeshellarg($tempFilePath) . " " . escapeshellarg($completeSubscribeUrl);
exec($command, $output, $returnVar);

View File

@ -149,17 +149,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['editFile'], $_GET['file
<?php
$subscriptionPath = '/etc/neko/proxy_provider/';
$subscriptionFile = $subscriptionPath . 'subscriptions.json';
$clashFile = $subscriptionPath . 'subscription_6.yaml';
$message = "";
$decodedContent = "";
$subscriptions = [];
$updateCompleted = false;
$updateCompleted = false;
function outputMessage($message) {
if (!isset($_SESSION['update_messages'])) {
$_SESSION['update_messages'] = array();
$_SESSION['update_messages'] = [];
}
$_SESSION['update_messages'][] = $message;
}
@ -176,7 +173,7 @@ if (!$subscriptions) {
for ($i = 0; $i < 6; $i++) {
$subscriptions[$i] = [
'url' => '',
'file_name' => "subscription_{$i}.yaml",
'file_name' => "subscription_" . ($i + 1) . ".yaml",
];
}
}
@ -184,13 +181,14 @@ if (!$subscriptions) {
if (isset($_POST['update'])) {
$index = intval($_POST['index']);
$url = $_POST['subscription_url'] ?? '';
$customFileName = $_POST['custom_file_name'] ?? "subscription_{$index}.yaml";
$customFileName = $_POST['custom_file_name'] ?? "subscription_" . ($index + 1) . ".yaml";
$subscriptions[$index]['url'] = $url;
$subscriptions[$index]['file_name'] = $customFileName;
if (!empty($url)) {
$finalPath = $subscriptionPath . $customFileName;
$command = "wget -q --show-progress -O {$finalPath} {$url}";
exec($command . ' 2>&1', $output, $return_var);
@ -209,16 +207,25 @@ if (isset($_POST['update'])) {
<li>该模板支持所有格式订阅链接,无需额外转换</li>
</ul>
</div>';
$_SESSION['update_messages'][] = "订阅链接 {$url} 更新成功!文件已保存到: {$finalPath}";
$message = '更新成功';
$updateCompleted = true;
$fileContent = file_get_contents($finalPath);
$decodedContent = base64_decode($fileContent);
if ($decodedContent === false) {
$_SESSION['update_messages'][] = "Base64 解码失败,请检查下载的文件内容是否有效!";
$message = "Base64 解码失败";
} else {
$clashFile = $subscriptionPath . $customFileName;
file_put_contents($clashFile, "# Clash Meta Config\n\n" . $decodedContent);
$_SESSION['update_messages'][] = "订阅链接 {$url} 更新成功,并解码内容保存到: {$clashFile}";
$message = '更新成功';
$updateCompleted = true;
}
} else {
$_SESSION['update_messages'] = array();
$_SESSION['update_messages'][] = "配置更新失败!错误信息: " . implode("\n", $output);
$message = '更新失败';
}
} else {
$_SESSION['update_messages'] = array();
$_SESSION['update_messages'][] = "" . ($index + 1) . "个订阅链接为空!";
$message = '更新失败';
}
@ -230,14 +237,13 @@ if (isset($_POST['convert_base64'])) {
$base64Content = $_POST['base64_content'] ?? '';
if (!empty($base64Content)) {
$decodedContent = base64_decode($base64Content);
$decodedContent = base64_decode($base64Content);
if ($decodedContent === false) {
$message = "Base64 解码失败,请检查输入";
$message = "Base64 解码失败,请检查输入内容";
} else {
$clashConfig = "# Clash Meta Config\n\n";
$clashConfig .= $decodedContent;
file_put_contents($clashFile, $clashConfig);
$clashFile = $subscriptionPath . 'decoded_subscription.yaml';
file_put_contents($clashFile, "# Clash Meta Config\n\n" . $decodedContent);
$message = "Clash 配置文件已生成并保存到: {$clashFile}";
}
} else {
@ -503,7 +509,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mihomo - Neko</title>
<title>Mihomo - 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">
@ -1188,30 +1194,36 @@ function initializeAceEditor() {
<?php if (isset($subscriptions) && is_array($subscriptions)): ?>
<div class="row">
<?php for ($i = 0; $i < 6; $i++): ?>
<?php
$maxSubscriptions = 6;
for ($i = 0; $i < $maxSubscriptions; $i++):
$displayIndex = $i + 1;
$url = $subscriptions[$i]['url'] ?? '';
$fileName = $subscriptions[$i]['file_name'] ?? "subscription_" . ($displayIndex) . ".yaml";
?>
<div class="col-md-4 mb-3">
<form method="post" class="card">
<div class="card-body">
<div class="form-group">
<h5 for="subscription_url_<?php echo $i; ?>" class="mb-2">订阅链接 <?php echo ($i + 1); ?></h5>
<input type="text" name="subscription_url" id="subscription_url_<?php echo $i; ?>" value="<?php echo htmlspecialchars($subscriptions[$i]['url'] ?? ''); ?>" required class="form-control">
<h5 for="subscription_url_<?php echo $displayIndex; ?>" class="mb-2">订阅链接 <?php echo $displayIndex; ?></h5>
<input type="text" name="subscription_url" id="subscription_url_<?php echo $displayIndex; ?>" value="<?php echo htmlspecialchars($url); ?>" class="form-control">
</div>
<div class="form-group">
<label for="custom_file_name_<?php echo $i; ?>">自定义文件名</label>
<input type="text" name="custom_file_name" id="custom_file_name_<?php echo $i; ?>" value="subscription_<?php echo ($i + 1); ?>.yaml" class="form-control">
<label for="custom_file_name_<?php echo $displayIndex; ?>">自定义文件名</label>
<input type="text" name="custom_file_name" id="custom_file_name_<?php echo $displayIndex; ?>" value="<?php echo htmlspecialchars($fileName); ?>" class="form-control">
</div>
<input type="hidden" name="index" value="<?php echo $i; ?>">
<div class="text-center mt-3">
<button type="submit" name="update" class="btn btn-info">🔄 更新订阅 <?php echo ($i + 1); ?></button>
<button type="submit" name="update" class="btn btn-info">🔄 更新订阅 <?php echo $displayIndex; ?></button>
</div>
</div>
</form>
</div>
<?php if (($i + 1) % 3 == 0 && $i < 5): ?>
<?php if (($displayIndex) % 3 == 0 && $displayIndex < $maxSubscriptions): ?>
</div><div class="row">
<?php endif; ?>
<?php endfor; ?>
</div>
<?php else: ?>

View File

@ -2,13 +2,13 @@
ob_start();
include './cfg.php';
date_default_timezone_set('Asia/Shanghai');
$proxyDir = '/www/nekobox/proxy/';
$uploadDir = '/etc/neko/proxy_provider/';
$configDir = '/etc/neko/config/';
ini_set('memory_limit', '256M');
if (!is_dir($proxyDir)) {
mkdir($proxyDir, 0755, true);
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
if (!is_dir($configDir)) {
@ -18,7 +18,7 @@ if (!is_dir($configDir)) {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_FILES['fileInput'])) {
$file = $_FILES['fileInput'];
$uploadFilePath = $proxyDir . basename($file['name']);
$uploadFilePath = $uploadDir . basename($file['name']);
if ($file['error'] === UPLOAD_ERR_OK) {
if (move_uploaded_file($file['tmp_name'], $uploadFilePath)) {
@ -47,7 +47,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if (isset($_POST['deleteFile'])) {
$fileToDelete = $proxyDir . basename($_POST['deleteFile']);
$fileToDelete = $uploadDir . basename($_POST['deleteFile']);
if (file_exists($fileToDelete) && unlink($fileToDelete)) {
echo '文件删除成功:' . htmlspecialchars(basename($_POST['deleteFile']));
} else {
@ -64,21 +64,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
}
if (isset($_POST['oldFileName'], $_POST['newFileName'], $_POST['fileType'])) {
$oldFileName = basename($_POST['oldFileName']);
$newFileName = basename($_POST['newFileName']);
$fileType = $_POST['fileType'];
if (isset($_POST['oldFileName'], $_POST['newFileName'], $_POST['fileType'])) {
$oldFileName = basename($_POST['oldFileName']);
$newFileName = basename($_POST['newFileName']);
$fileType = $_POST['fileType'];
if ($fileType === 'proxy') {
$oldFilePath = $proxyDir . $oldFileName;
$newFilePath = $proxyDir . $newFileName;
} elseif ($fileType === 'config') {
$oldFilePath = $configDir . $oldFileName;
$newFilePath = $configDir . $newFileName;
} else {
echo '无效的文件类型';
exit;
}
if ($fileType === 'proxy') {
$oldFilePath = $uploadDir. $oldFileName;
$newFilePath = $uploadDir. $newFileName;
} elseif ($fileType === 'config') {
$oldFilePath = $configDir . $oldFileName;
$newFilePath = $configDir . $newFileName;
} else {
echo '无效的文件类型';
exit;
}
if (file_exists($oldFilePath) && !file_exists($newFilePath)) {
if (rename($oldFilePath, $newFilePath)) {
@ -88,16 +88,16 @@ if (isset($_POST['oldFileName'], $_POST['newFileName'], $_POST['fileType'])) {
}
} else {
echo '文件重命名失败,文件不存在或新文件名已存在。';
}
}
}
if (isset($_POST['saveContent'], $_POST['fileName'], $_POST['fileType'])) {
$fileToSave = ($_POST['fileType'] === 'proxy') ? $proxyDir . basename($_POST['fileName']) : $configDir . basename($_POST['fileName']);
$contentToSave = $_POST['saveContent'];
file_put_contents($fileToSave, $contentToSave);
echo '<p>文件内容已更新:' . htmlspecialchars(basename($fileToSave)) . '</p>';
$fileToSave = ($_POST['fileType'] === 'proxy') ? $uploadDir . basename($_POST['fileName']) : $configDir . basename($_POST['fileName']);
$contentToSave = $_POST['saveContent'];
file_put_contents($fileToSave, $contentToSave);
echo '<p>文件内容已更新:' . htmlspecialchars(basename($fileToSave)) . '</p>';
}
}
}
function formatFileModificationTime($filePath) {
if (file_exists($filePath)) {
@ -108,7 +108,7 @@ function formatFileModificationTime($filePath) {
}
}
$proxyFiles = scandir($proxyDir);
$proxyFiles = scandir($uploadDir);
$configFiles = scandir($configDir);
if ($proxyFiles !== false) {
@ -134,7 +134,7 @@ function formatSize($size) {
}
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['editFile'], $_GET['fileType'])) {
$filePath = ($_GET['fileType'] === 'proxy') ? $proxyDir . basename($_GET['editFile']) : $configDir . basename($_GET['editFile']);
$filePath = ($_GET['fileType'] === 'proxy') ? $uploadDir. basename($_GET['editFile']) : $configDir . basename($_GET['editFile']);
if (file_exists($filePath)) {
header('Content-Type: text/plain');
echo file_get_contents($filePath);
@ -146,89 +146,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['editFile'], $_GET['file
}
?>
<?php
$configPath = '/www/nekobox/proxy/';
$configFile = $configPath . 'subscriptions.json';
$subscriptionList = [];
while (ob_get_level() > 0) {
ob_end_flush();
}
function outputMessage($message) {
if (!isset($_SESSION['notification_messages'])) {
$_SESSION['notification_messages'] = [];
}
$_SESSION['notification_messages'][] = $message;
}
if (!isset($_SESSION['help_message'])) {
$_SESSION['help_message'] = '<div class="text-warning" style="margin-bottom: 8px;">
<strong>⚠️ 注意:</strong> 当前配置文件必须配合 <strong>Puernya</strong> 内核使用,不支持其他内核!
</div>';
}
if (!file_exists($configPath)) {
mkdir($configPath, 0755, true);
}
if (!file_exists($configFile)) {
file_put_contents($configFile, json_encode([]));
}
$subscriptionList = json_decode(file_get_contents($configFile), true);
if (!$subscriptionList || !is_array($subscriptionList)) {
$subscriptionList = [];
for ($i = 1; $i <= 3; $i++) {
$subscriptionList[$i - 1] = [
'url' => '',
'file_name' => "subscription_{$i}.yaml",
];
}
}
if (isset($_POST['saveSubscription'])) {
$index = intval($_POST['index']);
if ($index >= 0 && $index < 3) {
$url = $_POST['subscription_url'] ?? '';
$customFileName = $_POST['custom_file_name'] ?? "subscription_{$index}.yaml";
$subscriptionList[$index]['url'] = $url;
$subscriptionList[$index]['file_name'] = $customFileName;
if (!empty($url)) {
$finalPath = $configPath . $customFileName;
$command = sprintf(
"wget -q --show-progress -O %s %s",
escapeshellarg($finalPath),
escapeshellarg($url)
);
exec($command . ' 2>&1', $output, $return_var);
if ($return_var !== 0) {
$command = sprintf(
"curl -s -o %s %s",
escapeshellarg($finalPath),
escapeshellarg($url)
);
exec($command . ' 2>&1', $output, $return_var);
}
if ($return_var === 0) {
outputMessage("订阅链接 {$url} 更新成功!文件已保存到: {$finalPath}");
} else {
outputMessage("配置更新失败!错误信息: " . implode("\n", $output));
}
} else {
outputMessage("" . ($index + 1) . "个订阅链接为空!");
}
file_put_contents($configFile, json_encode($subscriptionList));
}
}
$updateCompleted = isset($_POST['saveSubscription']);
?>
<?php
$subscriptionPath = '/etc/neko/config/';
$dataFile = $subscriptionPath . 'subscription_data.json';
@ -394,16 +311,6 @@ function isUtf8($string) {
<script src="./assets/bootstrap/popper.min.js"></script>
<script src="./assets/bootstrap/bootstrap.min.js"></script>
</head>
<?php if ($updateCompleted): ?>
<script>
if (!sessionStorage.getItem('refreshed')) {
sessionStorage.setItem('refreshed', 'true');
window.location.reload();
} else {
sessionStorage.removeItem('refreshed');
}
</script>
<?php endif; ?>
<body>
<div class="position-fixed w-100 d-flex justify-content-center" style="top: 20px; z-index: 1050">
@ -602,7 +509,7 @@ td {
<div class="card mb-4">
<div class="card-body">
<div class="container">
<h5>代理文件管理 p核专用</h5>
<h5>代理文件管理</h5>
<div class="table-responsive">
<table class="table table-striped table-bordered text-center">
<thead class="thead-dark">
@ -615,7 +522,7 @@ td {
</thead>
<tbody>
<?php foreach ($proxyFiles as $file): ?>
<?php $filePath = $proxyDir . $file; ?>
<?php $filePath = $uploadDir. $file; ?>
<tr>
<td class="align-middle"><a href="download.php?file=<?php echo urlencode($file); ?>"><?php echo htmlspecialchars($file); ?></a></td>
<td class="align-middle"><?php echo file_exists($filePath) ? formatSize(filesize($filePath)) : '文件不存在'; ?></td>
@ -1115,47 +1022,15 @@ function initializeAceEditor() {
</div>
</form>
<h2 class=" text-center mt-4 mb-4">订阅管理 p核专用</h2>
<div class="help-text mb-3 text-start">
<strong>1. 对于首次使用 Sing-box 的用户,必须将核心更新至版本 v1.10.0 或更高版本。确保将出站和入站/转发防火墙规则都设置为“接受”并启用它们。
</div>
<div class="help-text mb-3 text-start">
<strong>2. 注意:</strong> 通用模板(<code>puernya.json</code>)最多支持<strong>3 </strong>订阅链接。请勿更改默认文件名称,并确保使用 puernya 内核。
</div>
<div class="help-text mb-3 text-start">
<strong>3. 支持通用格式订阅,无需转换。
</div>
<div class="help-text mb-3 text-start">
<strong>4. 保存与更新:</strong> 填写完毕后,请点击"更新配置"按钮进行保存。
<strong>2. 注意puernya订阅已合并至Mihomo订阅并确保使用 puernya 内核。
</div>
<div class="help-text mb-3 text-start">
<strong>5. 说明:</strong> 上述 Sing-box 订阅适用于原版 Sing-box 内核,仅支持后缀为 Sing-box 格式的机场订阅链接。对于通用订阅,请使用转换模板以确保兼容性。
</div>
<div class="row">
<?php for ($i = 0; $i < 3; $i++): ?>
<div class="col-md-4 mb-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">订阅链接 <?php echo ($i + 1); ?></h5>
<form method="post">
<div class="input-group mb-3">
<input type="text" name="subscription_url" id="subscriptionurl<?php echo $i; ?>"
value="<?php echo htmlspecialchars($subscriptionList[$i]['url']); ?>"
required class="form-control" placeholder="输入链接">
<input type="text" name="custom_file_name" id="custom_filename<?php echo $i; ?>"
value="<?php echo htmlspecialchars($subscriptionList[$i]['file_name']); ?>"
class="form-control" placeholder="自定义文件名">
<input type="hidden" name="index" value="<?php echo $i; ?>">
<button type="submit" name="saveSubscription" class="btn btn-success ml-2">
<i>🔄</i> 更新
</button>
</div>
</form>
</div>
</div>
</div>
<?php endfor; ?>
</div>

View File

@ -506,7 +506,7 @@
"tag": "🛫 ",
"type": "remote",
"download_url": "https://example.com/xxx/xxx&flag=clash",
"path": "./proxy/subscription_1.yaml",
"path": "/etc/neko/proxy_provider/subscription_1.yaml",
"download_interval": "24h",
"download_ua": "clash.meta",
"includes": [
@ -520,7 +520,7 @@
"tag": "🛫. ",
"type": "remote",
"download_url": "https://example.com/xxx/xxx&flag=clash",
"path": "./proxy/subscription_2.yaml",
"path": "/etc/neko/proxy_provider/subscription_2.yaml",
"download_interval": "24h",
"download_ua": "clash.meta",
"includes": [
@ -534,7 +534,7 @@
"tag": "🛫.. ",
"type": "remote",
"download_url": "https://example.com/xxx/xxx&flag=clash",
"path": "./proxy/subscription_3.yaml",
"path": "/etc/neko/proxy_provider/subscription_3.yaml",
"download_interval": "24h",
"download_ua": "clash.meta",
"includes": [

View File

@ -24,7 +24,7 @@ return view.extend({
has_location = res[2].path,
pkgversion = '2.6';
var m, s, o;
let m, s, o;
m = new form.Map('tinyfilemanager');