mirror of
				https://github.com/kenzok8/openwrt-packages.git
				synced 2025-10-30 07:50:37 +08:00 
			
		
		
		
	update 2024-08-17 15:10:24
This commit is contained in:
		| @ -6,11 +6,19 @@ | ||||
| include $(TOPDIR)/rules.mk | ||||
|  | ||||
| PKG_NAME:=luci-app-alist | ||||
| PKG_VERSION:=1.1.0 | ||||
| PKG_VERSION:=1.0.13 | ||||
| PKG_RELEASE:=1 | ||||
|  | ||||
| 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 | ||||
|  | ||||
|  | ||||
| @ -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" | ||||
| msgstr "重置密码" | ||||
| 
 | ||||
| msgid "Generate a new random password." | ||||
| msgstr "随机生成一个新密码。" | ||||
| msgid "Reset" | ||||
| msgstr "重置" | ||||
| 
 | ||||
| msgid "Username:" | ||||
| msgstr "用户名:" | ||||
| 
 | ||||
| msgid "New Password:" | ||||
| msgstr "新密码:" | ||||
| 
 | ||||
| msgid "New password has been copied to clipboard." | ||||
| msgstr "新密码已复制到剪贴板。" | ||||
| msgid "Password:" | ||||
| msgstr "密码:" | ||||
| 
 | ||||
| msgid "Login Validity Period (hours)" | ||||
| 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": { | ||||
| 		"description": "Grant UCI access for luci-app-alist", | ||||
| 		"read": { | ||||
| 			"file": { | ||||
| 				"/usr/bin/alist": [ "exec" ], | ||||
| 				"/var/log/alist.log": [ "read" ] | ||||
| 			}, | ||||
| 			"ubus": { | ||||
| 				"service": [ "list" ] | ||||
| 			}, | ||||
| 			"uci": [ "alist" ] | ||||
| 		}, | ||||
| 		"write": { | ||||
| 			"file": { | ||||
| 				"/var/log/alist.log": [ "write" ] | ||||
| 			}, | ||||
| 			"uci": [ "alist" ] | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 actions-user
					actions-user