mirror of
https://github.com/kenzok8/openwrt-packages
synced 2025-01-07 07:06:45 +08:00
update 2024-08-17 15:10:24
This commit is contained in:
parent
bdb25187e4
commit
84763859d0
@ -6,11 +6,19 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=luci-app-alist
|
PKG_NAME:=luci-app-alist
|
||||||
PKG_VERSION:=1.1.0
|
PKG_VERSION:=1.0.13
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
LUCI_TITLE:=LuCI support for alist
|
LUCI_TITLE:=LuCI support for alist
|
||||||
LUCI_DEPENDS:=+alist
|
LUCI_DEPENDS:=+alist +luci-compat
|
||||||
|
|
||||||
|
define Package/$(PKG_NAME)/postinst
|
||||||
|
#!/bin/sh
|
||||||
|
[ -n "${IPKG_INSTROOT}" ] || {
|
||||||
|
( . /etc/uci-defaults/50-luci-alist ) && rm -f /etc/uci-defaults/50-luci-alist
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
endef
|
||||||
|
|
||||||
include $(TOPDIR)/feeds/luci/luci.mk
|
include $(TOPDIR)/feeds/luci/luci.mk
|
||||||
|
|
||||||
|
@ -1,199 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
'require form';
|
|
||||||
'require fs';
|
|
||||||
'require poll';
|
|
||||||
'require rpc';
|
|
||||||
'require uci';
|
|
||||||
'require view';
|
|
||||||
|
|
||||||
var callServiceList = rpc.declare({
|
|
||||||
object: 'service',
|
|
||||||
method: 'list',
|
|
||||||
params: ['name'],
|
|
||||||
expect: { '': {} }
|
|
||||||
});
|
|
||||||
|
|
||||||
function getServiceStatus() {
|
|
||||||
return L.resolveDefault(callServiceList('alist'), {}).then(function (res) {
|
|
||||||
var isRunning = false;
|
|
||||||
try {
|
|
||||||
isRunning = res['alist']['instances']['alist']['running'];
|
|
||||||
} catch (e) { }
|
|
||||||
return isRunning;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderStatus(isRunning, protocol, webport) {
|
|
||||||
var spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
|
|
||||||
var renderHTML;
|
|
||||||
if (isRunning) {
|
|
||||||
var button = String.format('<input class="cbi-button-reload" type="button" style="margin-left: 50px" value="%s" onclick="window.open(\'%s//%s:%s/\')">',
|
|
||||||
_('Open Web Interface'), protocol, window.location.hostname, webport);
|
|
||||||
renderHTML = spanTemp.format('green', 'Alist', _('RUNNING')) + button;
|
|
||||||
} else {
|
|
||||||
renderHTML = spanTemp.format('red', 'Alist', _('NOT RUNNING'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return renderHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
return view.extend({
|
|
||||||
load: function () {
|
|
||||||
return Promise.all([
|
|
||||||
uci.load('alist')
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleResetPassword: async function (data) {
|
|
||||||
var data_dir = uci.get(data[0], '@alist[0]', 'data_dir') || '/etc/alist';
|
|
||||||
try {
|
|
||||||
var newpassword = await fs.exec('/usr/bin/alist', ['admin', 'random', '--data', data_dir]);
|
|
||||||
var new_password = newpassword.stderr.match(/password:\s*(\S+)/)[1];
|
|
||||||
const textArea = document.createElement('textarea');
|
|
||||||
textArea.value = new_password;
|
|
||||||
document.body.appendChild(textArea);
|
|
||||||
textArea.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(textArea);
|
|
||||||
alert(_('Username:') + 'admin\n' + _('New Password:') + new_password + '\n\n' + _('New password has been copied to clipboard.'));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to reset password: ', error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function (data) {
|
|
||||||
var m, s, o;
|
|
||||||
var webport = uci.get(data[0], '@alist[0]', 'port') || '5244';
|
|
||||||
var ssl = uci.get(data[0], '@alist[0]', 'ssl') || '0';
|
|
||||||
var protocol;
|
|
||||||
if (ssl === '0') {
|
|
||||||
protocol = 'http:';
|
|
||||||
} else if (ssl === '1') {
|
|
||||||
protocol = 'https:';
|
|
||||||
}
|
|
||||||
|
|
||||||
m = new form.Map('alist', _('Alist'),
|
|
||||||
_('A file list program that supports multiple storage.') +
|
|
||||||
'<br><a href="https://alist.nn.ci/zh/guide/drivers/local.html" target="_blank">' +
|
|
||||||
_('User Manual') +
|
|
||||||
'</a>');
|
|
||||||
|
|
||||||
s = m.section(form.TypedSection);
|
|
||||||
s.anonymous = true;
|
|
||||||
s.addremove = false;
|
|
||||||
|
|
||||||
s.render = function () {
|
|
||||||
poll.add(function () {
|
|
||||||
return L.resolveDefault(getServiceStatus()).then(function (res) {
|
|
||||||
var view = document.getElementById('service_status');
|
|
||||||
view.innerHTML = renderStatus(res, protocol, webport);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
|
|
||||||
E('p', { id: 'service_status' }, _('Collecting data...'))
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
s = m.section(form.NamedSection, '@alist[0]', 'alist');
|
|
||||||
|
|
||||||
o = s.option(form.Flag, 'enabled', _('Enabled'));
|
|
||||||
o.default = o.disabled;
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'port', _('Port'));
|
|
||||||
o.datatype = 'and(port,min(1))';
|
|
||||||
o.default = '5244';
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Flag, 'log', _('Enable Logs'));
|
|
||||||
o.default = 1;
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Flag, 'ssl', _('Enable SSL'));
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'ssl_cert', _('SSL cert'),
|
|
||||||
_('SSL certificate file path'));
|
|
||||||
o.rmempty = false;
|
|
||||||
o.depends('ssl', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'ssl_key', _('SSL key'),
|
|
||||||
_('SSL key file path'));
|
|
||||||
o.rmempty = false;
|
|
||||||
o.depends('ssl', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Flag, 'mysql', _('Enable Database'));
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.ListValue, 'mysql_type', _('Database Type'));
|
|
||||||
o.default = 'mysql';
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
o.value('mysql', _('MySQL'));
|
|
||||||
o.value('postgres', _('PostgreSQL'));
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_host', _('Database Host'));
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_port', _('Database Port'));
|
|
||||||
o.datatype = 'port';
|
|
||||||
o.default = '3306';
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_username', _('Database Username'));
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_password', _('Database Password'));
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_database', _('Database Name'));
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_table_prefix', _('Database Table Prefix'));
|
|
||||||
o.default = 'x_';
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_ssl_mode', _('Database SSL Mode'));
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'mysql_dsn', _('Database DSN'));
|
|
||||||
o.depends('mysql', '1');
|
|
||||||
|
|
||||||
o = s.option(form.Flag, 'allow_wan', _('Allow Access From Internet'));
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'site_url', _('Site URL'),
|
|
||||||
_('When the web is reverse proxied to a subdirectory, this option must be filled out to ensure proper functioning of the web. Do not include \'/\' at the end of the URL'));
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'max_connections', _('Max Connections'),
|
|
||||||
_('0 is unlimited, It is recommend to set a low number of concurrency (10-20) for poor performance device'));
|
|
||||||
o.default = '0';
|
|
||||||
o.datatype = 'uinteger';
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'token_expires_in', _('Login Validity Period (hours)'));
|
|
||||||
o.datatype = 'uinteger';
|
|
||||||
o.default = '48';
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'delayed_start', _('Delayed Start (seconds)'));
|
|
||||||
o.datatype = 'uinteger';
|
|
||||||
o.default = '0';
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'data_dir', _('Data directory'));
|
|
||||||
o.default = '/etc/alist';
|
|
||||||
|
|
||||||
o = s.option(form.Value, 'temp_dir', _('Cache directory'));
|
|
||||||
o.default = '/tmp/alist';
|
|
||||||
o.rmempty = false;
|
|
||||||
|
|
||||||
o = s.option(form.Button, '_newpassword', _('Reset Password'),
|
|
||||||
_('Generate a new random password.'));
|
|
||||||
o.inputtitle = _('Reset Password');
|
|
||||||
o.inputstyle = 'apply';
|
|
||||||
o.onclick = L.bind(this.handleResetPassword, this, data);
|
|
||||||
|
|
||||||
return m.render();
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,76 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
'require dom';
|
|
||||||
'require fs';
|
|
||||||
'require poll';
|
|
||||||
'require view';
|
|
||||||
|
|
||||||
function pollLog(e) {
|
|
||||||
return Promise.all([
|
|
||||||
fs.read_direct('/var/log/alist.log', 'text').then(function (res) {
|
|
||||||
return res.trim().split(/\n/).join('\n').replace(/\u001b\[33mWARN\u001b\[0m/g, '').replace(/\u001b\[36mINFO\u001b\[0m/g, '');
|
|
||||||
}),
|
|
||||||
]).then(function (data) {
|
|
||||||
var logTextarea = E('textarea', { 'class': 'cbi-input-textarea', 'wrap': 'off', 'readonly': 'readonly', 'style': 'width: calc(100% - 20px);height: 500px;margin: 10px;overflow-y: scroll;' }, [
|
|
||||||
data[0] || _('No log data.')
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Store the current scroll position
|
|
||||||
var storedScrollTop = e.querySelector('textarea') ? e.querySelector('textarea').scrollTop : null;
|
|
||||||
|
|
||||||
dom.content(e, logTextarea);
|
|
||||||
|
|
||||||
// If the storedScrollTop is not null, it means we have a previous scroll position
|
|
||||||
if (storedScrollTop !== null) {
|
|
||||||
logTextarea.scrollTop = storedScrollTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add event listener to save the scroll position when scrolling stops
|
|
||||||
var timer;
|
|
||||||
logTextarea.addEventListener('scroll', function () {
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = setTimeout(function () {
|
|
||||||
storeScrollPosition(logTextarea.scrollTop);
|
|
||||||
}, 150);
|
|
||||||
});
|
|
||||||
|
|
||||||
function storeScrollPosition(scrollPos) {
|
|
||||||
localStorage.setItem("scrollPosition", JSON.stringify({ "log": scrollPos }));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return view.extend({
|
|
||||||
handleCleanLogs: function () {
|
|
||||||
return fs.write('/var/log/alist.log', '')
|
|
||||||
.catch(function (e) { ui.addNotification(null, E('p', e.message)) });
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function () {
|
|
||||||
var log_textarea = E('div', { 'id': 'log_textarea' },
|
|
||||||
E('img', {
|
|
||||||
'src': L.resource(['icons/loading.gif']),
|
|
||||||
'alt': _('Loading'),
|
|
||||||
'style': 'vertical-align:middle'
|
|
||||||
}, _('Collecting data...'))
|
|
||||||
);
|
|
||||||
|
|
||||||
poll.add(pollLog.bind(this, log_textarea));
|
|
||||||
var clear_logs_button = E('input', { 'class': 'btn cbi-button-action', 'type': 'button', 'style': 'margin-left: 10px; margin-top: 10px;', 'value': _('Clear logs') });
|
|
||||||
clear_logs_button.addEventListener('click', this.handleCleanLogs.bind(this));
|
|
||||||
return E([
|
|
||||||
E('div', { 'class': 'cbi-map' }, [
|
|
||||||
E('div', { 'class': 'cbi-section' }, [
|
|
||||||
clear_logs_button,
|
|
||||||
log_textarea,
|
|
||||||
E('div', { 'style': 'text-align:right' },
|
|
||||||
E('small', {}, _('Refresh every %s seconds.').format(L.env.pollinterval))
|
|
||||||
)
|
|
||||||
])])
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
handleSave: null,
|
|
||||||
handleSaveApply: null,
|
|
||||||
handleReset: null
|
|
||||||
});
|
|
50
luci-app-alist/luasrc/controller/alist.lua
Normal file
50
luci-app-alist/luasrc/controller/alist.lua
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
module("luci.controller.alist", package.seeall)
|
||||||
|
|
||||||
|
function index()
|
||||||
|
if not nixio.fs.access("/etc/config/alist") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local page = entry({"admin", "nas", "alist"}, alias("admin", "nas", "alist", "basic"), _("Alist"), 20)
|
||||||
|
page.dependent = true
|
||||||
|
page.acl_depends = { "luci-app-alist" }
|
||||||
|
|
||||||
|
entry({"admin", "nas"}, firstchild(), "NAS", 44).dependent = false
|
||||||
|
entry({"admin", "nas", "alist", "basic"}, cbi("alist/basic"), _("Basic Setting"), 1).leaf = true
|
||||||
|
entry({"admin", "nas", "alist", "log"}, cbi("alist/log"), _("Logs"), 2).leaf = true
|
||||||
|
entry({"admin", "nas", "alist", "alist_status"}, call("alist_status")).leaf = true
|
||||||
|
entry({"admin", "nas", "alist", "get_log"}, call("get_log")).leaf = true
|
||||||
|
entry({"admin", "nas", "alist", "clear_log"}, call("clear_log")).leaf = true
|
||||||
|
entry({"admin", "nas", "alist", "admin_info"}, call("admin_info")).leaf = true
|
||||||
|
end
|
||||||
|
|
||||||
|
function alist_status()
|
||||||
|
local sys = require "luci.sys"
|
||||||
|
local uci = require "luci.model.uci".cursor()
|
||||||
|
local port = tonumber(uci:get_first("alist", "alist", "port"))
|
||||||
|
|
||||||
|
local status = {
|
||||||
|
running = (sys.call("pidof alist >/dev/null") == 0),
|
||||||
|
port = (port or 5244)
|
||||||
|
}
|
||||||
|
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
luci.http.write_json(status)
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_log()
|
||||||
|
luci.http.write(luci.sys.exec("cat /var/log/alist.log"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function clear_log()
|
||||||
|
luci.sys.call("cat /dev/null > /var/log/alist.log")
|
||||||
|
end
|
||||||
|
|
||||||
|
function admin_info()
|
||||||
|
local random = luci.sys.exec("/usr/bin/alist --data $(uci -q get alist.@alist[0].data_dir) admin random 2>&1")
|
||||||
|
local username = string.match(random, "username: (%S+)")
|
||||||
|
local password = string.match(random, "password: (%S+)")
|
||||||
|
|
||||||
|
luci.http.prepare_content("application/json")
|
||||||
|
luci.http.write_json({username = username, password = password})
|
||||||
|
end
|
113
luci-app-alist/luasrc/model/cbi/alist/basic.lua
Normal file
113
luci-app-alist/luasrc/model/cbi/alist/basic.lua
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
local m, s
|
||||||
|
|
||||||
|
m = Map("alist", translate("Alist"), translate("A file list program that supports multiple storage.") .. "<br/>" .. [[<a href="https://alist.nn.ci/zh/guide/drivers/local.html" target="_blank">]] .. translate("User Manual") .. [[</a>]])
|
||||||
|
|
||||||
|
m:section(SimpleSection).template = "alist/alist_status"
|
||||||
|
|
||||||
|
s = m:section(TypedSection, "alist")
|
||||||
|
s.addremove = false
|
||||||
|
s.anonymous = true
|
||||||
|
|
||||||
|
o = s:option(Flag, "enabled", translate("Enabled"))
|
||||||
|
o.rmempty = false
|
||||||
|
|
||||||
|
o = s:option(Value, "port", translate("Port"))
|
||||||
|
o.datatype = "and(port,min(1))"
|
||||||
|
o.rmempty = false
|
||||||
|
o.default = "5244"
|
||||||
|
|
||||||
|
o = s:option(Flag, "log", translate("Enable Logs"))
|
||||||
|
o.default = 1
|
||||||
|
o.rmempty = false
|
||||||
|
|
||||||
|
o = s:option(Flag, "ssl", translate("Enable SSL"))
|
||||||
|
o.rmempty=false
|
||||||
|
|
||||||
|
o = s:option(Value,"ssl_cert", translate("SSL cert"), translate("SSL certificate file path"))
|
||||||
|
o.datatype = "file"
|
||||||
|
o:depends("ssl", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"ssl_key", translate("SSL key"), translate("SSL key file path"))
|
||||||
|
o.datatype = "file"
|
||||||
|
o:depends("ssl", "1")
|
||||||
|
|
||||||
|
o = s:option(Flag, "mysql", translate("Enable Database"))
|
||||||
|
o.rmempty=false
|
||||||
|
|
||||||
|
o = s:option(ListValue, "mysql_type", translate("Database Type"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o:value("mysql", translate("MySQL"))
|
||||||
|
o:value("postgres", translate("PostgreSQL"))
|
||||||
|
o.default = "mysql"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_host", translate("Database Host"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_port", translate("Database Port"))
|
||||||
|
o.datatype = "and(port,min(1))"
|
||||||
|
o.default = "3306"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_username", translate("Database Username"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_password", translate("Database Password"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o.password = true
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_database", translate("Database Name"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_table_prefix", translate("Database Table Prefix"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o.default = "x_"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_ssl_mode", translate("Database SSL Mode"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Value,"mysql_dsn", translate("Database DSN"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o:depends("mysql", "1")
|
||||||
|
|
||||||
|
o = s:option(Flag, "allow_wan", translate("Allow Access From Internet"))
|
||||||
|
o.rmempty = false
|
||||||
|
|
||||||
|
o = s:option(Value, "site_url", translate("Site URL"), translate("When the web is reverse proxied to a subdirectory, this option must be filled out to ensure proper functioning of the web. Do not include '/' at the end of the URL"))
|
||||||
|
o.datatype = "string"
|
||||||
|
|
||||||
|
o = s:option(Value, "max_connections", translate("Max Connections"), translate("0 is unlimited, It is recommend to set a low number of concurrency (10-20) for poor performance device"))
|
||||||
|
o.datatype = "and(uinteger,min(0))"
|
||||||
|
o.default = "0"
|
||||||
|
o.rmempty = false
|
||||||
|
|
||||||
|
o = s:option(Value, "token_expires_in", translate("Login Validity Period (hours)"))
|
||||||
|
o.datatype = "and(uinteger,min(1))"
|
||||||
|
o.default = "48"
|
||||||
|
o.rmempty = false
|
||||||
|
|
||||||
|
o = s:option(Value, "delayed_start", translate("Delayed Start (seconds)"))
|
||||||
|
o.datatype = "and(uinteger,min(0))"
|
||||||
|
o.default = "0"
|
||||||
|
o.rmempty = false
|
||||||
|
|
||||||
|
o = s:option(Value, "data_dir", translate("Data directory"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o.default = "/etc/alist"
|
||||||
|
|
||||||
|
o = s:option(Value, "temp_dir", translate("Cache directory"))
|
||||||
|
o.datatype = "string"
|
||||||
|
o.default = "/tmp/alist"
|
||||||
|
o.rmempty = false
|
||||||
|
|
||||||
|
o = s:option(Button, "admin_info", translate("Reset Password"))
|
||||||
|
o.rawhtml = true
|
||||||
|
o.template = "alist/admin_info"
|
||||||
|
|
||||||
|
return m
|
5
luci-app-alist/luasrc/model/cbi/alist/log.lua
Normal file
5
luci-app-alist/luasrc/model/cbi/alist/log.lua
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
m = Map("alist")
|
||||||
|
|
||||||
|
m:append(Template("alist/alist_log"))
|
||||||
|
|
||||||
|
return m
|
26
luci-app-alist/luasrc/view/alist/admin_info.htm
Normal file
26
luci-app-alist/luasrc/view/alist/admin_info.htm
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<%+cbi/valueheader%>
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
function admin_info(btn)
|
||||||
|
{
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.value = '<%:Collecting data...%>';
|
||||||
|
XHR.get('<%=luci.dispatcher.build_url("admin", "nas", "alist", "admin_info")%>',
|
||||||
|
null,
|
||||||
|
function(x,rv)
|
||||||
|
{
|
||||||
|
var tb = document.getElementById('<%=self.option%>-status');
|
||||||
|
if (tb)
|
||||||
|
{
|
||||||
|
tb.innerHTML = "<%:Username:%>" + "<font color='green'>" + rv.username + "</font>";
|
||||||
|
tb.innerHTML += "<%:Password:%>" + "<font color='green'>" + rv.password + "</font>";
|
||||||
|
}
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.value = '<%:Reset%>';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//]]></script>
|
||||||
|
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Reset%>" onclick="return admin_info(this)" />
|
||||||
|
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||||
|
<%+cbi/valuefooter%>
|
35
luci-app-alist/luasrc/view/alist/alist_log.htm
Normal file
35
luci-app-alist/luasrc/view/alist/alist_log.htm
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
|
function clear_log(btn) {
|
||||||
|
XHR.get('<%=url([[admin]], [[nas]], [[alist]], [[clear_log]])%>', null,
|
||||||
|
function(x, data) {
|
||||||
|
if(x && x.status == 200) {
|
||||||
|
var log_textarea = document.getElementById('log_textarea');
|
||||||
|
log_textarea.innerHTML = "";
|
||||||
|
log_textarea.scrollTop = log_textarea.scrollHeight;
|
||||||
|
}
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var scrolled = false;
|
||||||
|
XHR.poll(2, '<%=url([[admin]], [[nas]], [[alist]], [[get_log]])%>', null,
|
||||||
|
function(x, data) {
|
||||||
|
if(x && x.status == 200) {
|
||||||
|
var log_textarea = document.getElementById('log_textarea');
|
||||||
|
var str = x.responseText;
|
||||||
|
var logs = str.replace(//g, "🔧");
|
||||||
|
log_textarea.innerHTML = logs;
|
||||||
|
if (!scrolled) {
|
||||||
|
log_textarea.scrollTop = log_textarea.scrollHeight;
|
||||||
|
scrolled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
<fieldset class="cbi-section" id="_log_fieldset">
|
||||||
|
<input class="cbi-button cbi-input-remove" type="button" onclick="clear_log()" value="<%:Clear logs%>" style="margin-left: 10px; margin-top: 10px;">
|
||||||
|
<textarea id="log_textarea" class="cbi-input-textarea" style="width: calc(100% - 20px); height: 500px; margin: 10px;" data-update="change" rows="5" wrap="off" readonly="readonly"></textarea>
|
||||||
|
</fieldset>
|
36
luci-app-alist/luasrc/view/alist/alist_status.htm
Normal file
36
luci-app-alist/luasrc/view/alist/alist_status.htm
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<%
|
||||||
|
local uci = require 'luci.model.uci'.cursor()
|
||||||
|
ssl = uci:get_first('alist', 'alist', 'ssl')
|
||||||
|
if ssl == '1' then
|
||||||
|
protocol="https://"
|
||||||
|
else
|
||||||
|
protocol="http://"
|
||||||
|
end
|
||||||
|
%>
|
||||||
|
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
XHR.poll(5, '<%=url("admin/nas/alist/alist_status")%>', null,
|
||||||
|
function(x, st)
|
||||||
|
{
|
||||||
|
var tb = document.getElementById('alist_status');
|
||||||
|
if (st && tb)
|
||||||
|
{
|
||||||
|
if (st.running)
|
||||||
|
{
|
||||||
|
tb.innerHTML = '<em style=\"color:green\"><b>Alist <%:RUNNING%></b></em>' + "<input class=\"cbi-button cbi-button-reload mar-10\" type=\"button\" value=\" <%:Open Web Interface%> \" onclick=\"window.open('<%=protocol%>" + window.location.hostname + ":" + st.port + "/')\"/>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tb.innerHTML = '<em style=\"color:red\"><b>Alist <%:NOT RUNNING%></b></em>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
//]]></script>
|
||||||
|
|
||||||
|
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
|
||||||
|
<fieldset class="cbi-section">
|
||||||
|
<p id="alist_status">
|
||||||
|
<em><b><%:Collecting data...%></b></em>
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
@ -1 +0,0 @@
|
|||||||
zh_Hans
|
|
@ -67,17 +67,14 @@ msgstr "清空日志"
|
|||||||
msgid "Reset Password"
|
msgid "Reset Password"
|
||||||
msgstr "重置密码"
|
msgstr "重置密码"
|
||||||
|
|
||||||
msgid "Generate a new random password."
|
msgid "Reset"
|
||||||
msgstr "随机生成一个新密码。"
|
msgstr "重置"
|
||||||
|
|
||||||
msgid "Username:"
|
msgid "Username:"
|
||||||
msgstr "用户名:"
|
msgstr "用户名:"
|
||||||
|
|
||||||
msgid "New Password:"
|
msgid "Password:"
|
||||||
msgstr "新密码:"
|
msgstr "密码:"
|
||||||
|
|
||||||
msgid "New password has been copied to clipboard."
|
|
||||||
msgstr "新密码已复制到剪贴板。"
|
|
||||||
|
|
||||||
msgid "Login Validity Period (hours)"
|
msgid "Login Validity Period (hours)"
|
||||||
msgstr "登录有效期(小时)"
|
msgstr "登录有效期(小时)"
|
1
luci-app-alist/po/zh_Hans
Symbolic link
1
luci-app-alist/po/zh_Hans
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
zh-cn
|
@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"admin/nas": {
|
|
||||||
"title": "NAS",
|
|
||||||
"order": 44,
|
|
||||||
"action": {
|
|
||||||
"type": "firstchild"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"admin/nas/alist": {
|
|
||||||
"title": "Alist",
|
|
||||||
"order": 20,
|
|
||||||
"action": {
|
|
||||||
"type": "firstchild"
|
|
||||||
},
|
|
||||||
"depends": {
|
|
||||||
"acl": [ "luci-app-alist" ],
|
|
||||||
"uci": { "alist": true }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"admin/nas/alist/basic": {
|
|
||||||
"title": "Basic Setting",
|
|
||||||
"order": 30,
|
|
||||||
"action": {
|
|
||||||
"type": "view",
|
|
||||||
"path": "alist/basic"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"admin/nas/alist/logs": {
|
|
||||||
"title": "Logs",
|
|
||||||
"order": 40,
|
|
||||||
"action": {
|
|
||||||
"type": "view",
|
|
||||||
"path": "alist/logs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,19 +2,9 @@
|
|||||||
"luci-app-alist": {
|
"luci-app-alist": {
|
||||||
"description": "Grant UCI access for luci-app-alist",
|
"description": "Grant UCI access for luci-app-alist",
|
||||||
"read": {
|
"read": {
|
||||||
"file": {
|
|
||||||
"/usr/bin/alist": [ "exec" ],
|
|
||||||
"/var/log/alist.log": [ "read" ]
|
|
||||||
},
|
|
||||||
"ubus": {
|
|
||||||
"service": [ "list" ]
|
|
||||||
},
|
|
||||||
"uci": [ "alist" ]
|
"uci": [ "alist" ]
|
||||||
},
|
},
|
||||||
"write": {
|
"write": {
|
||||||
"file": {
|
|
||||||
"/var/log/alist.log": [ "write" ]
|
|
||||||
},
|
|
||||||
"uci": [ "alist" ]
|
"uci": [ "alist" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user