small-packages/luci-app-nikki/htdocs/luci-static/resources/tools/nikki.js
2026-06-16 17:21:41 +08:00

228 lines
6.0 KiB
JavaScript

'use strict';
'require baseclass';
'require uci';
'require fs';
'require rpc';
'require request';
const callRCList = rpc.declare({
object: 'rc',
method: 'list',
params: ['name'],
expect: { '': {} }
});
const callRCInit = rpc.declare({
object: 'rc',
method: 'init',
params: ['name', 'action'],
expect: { '': {} }
});
const callFileWrite = rpc.declare({
object: 'file',
method: 'write',
params: ['path', 'data', 'append', 'mode']
});
const callNikkiVersion = rpc.declare({
object: 'luci.nikki',
method: 'version',
expect: { '': {} }
});
const callNikkiProfile = rpc.declare({
object: 'luci.nikki',
method: 'profile',
params: ['defaults'],
expect: { '': {} }
});
const callNikkiUpdateSubscription = rpc.declare({
object: 'luci.nikki',
method: 'update_subscription',
params: ['section_id'],
expect: { '': {} }
});
const callNikkiAPI = rpc.declare({
object: 'luci.nikki',
method: 'api',
params: ['method', 'path', 'query', 'body'],
expect: { '': {} }
});
const callNikkiGetIdentifiers = rpc.declare({
object: 'luci.nikki',
method: 'get_identifiers',
expect: { '': {} }
});
const callNikkiDebug = rpc.declare({
object: 'luci.nikki',
method: 'debug',
expect: { '': {} }
});
const homeDir = '/etc/nikki';
const profilesDir = `${homeDir}/profiles`;
const subscriptionsDir = `${homeDir}/subscriptions`;
const mixinFilePath = `${homeDir}/mixin.yaml`;
const runDir = `${homeDir}/run`;
const runProfilePath = `${runDir}/config.yaml`;
const providersDir = `${runDir}/providers`;
const ruleProvidersDir = `${providersDir}/rule`;
const proxyProvidersDir = `${providersDir}/proxy`;
const logDir = `/var/log/nikki`;
const appLogPath = `${logDir}/app.log`;
const coreLogPath = `${logDir}/core.log`;
const debugLogPath = `${logDir}/debug.log`;
const nftDir = `${homeDir}/nftables`;
return baseclass.extend({
homeDir: homeDir,
profilesDir: profilesDir,
subscriptionsDir: subscriptionsDir,
mixinFilePath: mixinFilePath,
runDir: runDir,
runProfilePath: runProfilePath,
ruleProvidersDir: ruleProvidersDir,
proxyProvidersDir: proxyProvidersDir,
appLogPath: appLogPath,
coreLogPath: coreLogPath,
debugLogPath: debugLogPath,
status: async function () {
return (await callRCList('nikki'))?.nikki?.running;
},
reload: function () {
return callRCInit('nikki', 'reload');
},
restart: function () {
return callRCInit('nikki', 'restart');
},
writefile: function (path, data, mode) {
data = (data != null) ? String(data) : '';
mode = (mode != null) ? mode : 0o644;
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const chunkSize = 8 * 1024;
const bytes = encoder.encode(data);
if (bytes.length <= chunkSize) {
return callFileWrite(path, data, false, mode);
}
let promise = Promise.resolve();
for(let offset = 0; offset < bytes.length; offset += chunkSize) {
const chunkBytes = bytes.slice(offset, Math.min(offset + chunkSize, bytes.length));
const chunk = decoder.decode(chunkBytes);
const append = offset > 0;
promise = promise.then(() => callFileWrite(path, chunk, append, mode));
}
return promise;
},
version: function () {
return callNikkiVersion();
},
profile: function (defaults) {
return callNikkiProfile(defaults);
},
updateSubscription: function (section_id) {
return callNikkiUpdateSubscription(section_id);
},
updateDashboard: function () {
return callNikkiAPI('POST', '/upgrade/ui');
},
openDashboard: async function () {
const profile = await callNikkiProfile({
'external-ui-name': null,
'external-controller': null,
'external-controller-tls': null,
'secret': null
});
const uiName = profile['external-ui-name'];
const apiListen = profile['external-controller'];
const apiTLSListen = profile['external-controller-tls'];
const apiSecret = profile['secret'] ?? '';
if (!apiListen && !apiTLSListen) {
return Promise.reject('API has not been configured');
}
let protocol;
let port;
if (apiTLSListen) {
protocol = 'https';
port = apiTLSListen.substring(apiTLSListen.lastIndexOf(':') + 1);
} else {
protocol = 'http';
port = apiListen.substring(apiListen.lastIndexOf(':') + 1);
}
const params = {
host: window.location.hostname,
hostname: window.location.hostname,
port: port,
secret: apiSecret
};
const query = new URLSearchParams(params).toString();
let url;
if (uiName) {
url = `${protocol}://${window.location.hostname}:${port}/ui/${uiName}/?${query}`;
} else {
url = `${protocol}://${window.location.hostname}:${port}/ui/?${query}`;
}
setTimeout(function () { window.open(url, '_blank') }, 0);
return Promise.resolve();
},
getIdentifiers: function () {
return callNikkiGetIdentifiers();
},
listProfiles: function () {
return L.resolveDefault(fs.list(this.profilesDir), []);
},
listRuleProviders: function () {
return L.resolveDefault(fs.list(this.ruleProvidersDir), []);
},
listProxyProviders: function () {
return L.resolveDefault(fs.list(this.proxyProvidersDir), []);
},
getAppLog: function () {
return L.resolveDefault(fs.read_direct(this.appLogPath));
},
getCoreLog: function () {
return L.resolveDefault(fs.read_direct(this.coreLogPath));
},
clearAppLog: function () {
return this.writefile(this.appLogPath, '');
},
clearCoreLog: function () {
return this.writefile(this.coreLogPath, '');
},
debug: function () {
return callNikkiDebug();
},
})