/* * SPDX-License-Identifier: GPL-2.0-only * * Copyright (C) 2022-2023 ImmortalWrt.org */ 'use strict'; 'require dom'; 'require form'; 'require fs'; 'require poll'; 'require rpc'; 'require uci'; 'require ui'; 'require view'; /* Thanks to luci-app-aria2 */ var css = ' \ #log_textarea { \ padding: 10px; \ text-align: left; \ } \ #log_textarea pre { \ padding: .5rem; \ word-break: break-all; \ margin: 0; \ } \ .description { \ background-color: #33ccff; \ }'; var hp_dir = '/var/run/homeproxy'; function getConnStat(self, site) { var callConnStat = rpc.declare({ object: 'luci.homeproxy', method: 'connection_check', params: ['site'], expect: { '': {} } }); self.default = E('div', { 'style': 'cbi-value-field' }, [ E('button', { 'class': 'btn cbi-button cbi-button-action', 'click': ui.createHandlerFn(this, function() { return L.resolveDefault(callConnStat(site), {}).then((ret) => { var ele = self.default.firstElementChild.nextElementSibling; if (ret.result) { ele.style.setProperty('color', 'green'); ele.innerHTML = _('passed'); } else { ele.style.setProperty('color', 'red'); ele.innerHTML = _('failed'); } }); }) }, [ _('Check') ]), ' ', E('strong', { 'style': 'color:gray' }, _('unchecked')), ]); } function getResVersion(self, type) { var callResVersion = rpc.declare({ object: 'luci.homeproxy', method: 'resources_get_version', params: ['type'], expect: { '': {} } }); var callResUpdate = rpc.declare({ object: 'luci.homeproxy', method: 'resources_update', params: ['type'], expect: { '': {} } }); return L.resolveDefault(callResVersion(type), {}).then((res) => { var spanTemp = E('div', { 'style': 'cbi-value-field' }, [ E('button', { 'class': 'btn cbi-button cbi-button-action', 'click': ui.createHandlerFn(this, function() { return L.resolveDefault(callResUpdate(type), {}).then((res) => { switch (res.status) { case 0: self.description = _('Successfully updated.'); break; case 1: self.description = _('Update failed.'); break; case 2: self.description = _('Already in updating.'); break; case 3: self.description = _('Already at the latest version.'); break; default: self.description = _('Unknown error.'); break; } return self.map.reset(); }); }) }, [ _('Check update') ]), ' ', E('strong', { 'style': (res.error ? 'color:red' : 'color:green') }, [ res.error ? 'not found' : res.version ] ), ]); self.default = spanTemp; }); } function getRuntimeLog(name, filename) { var callLogClean = rpc.declare({ object: 'luci.homeproxy', method: 'log_clean', params: ['type'], expect: { '': {} } }); var log_textarea = E('div', { 'id': 'log_textarea' }, E('img', { 'src': L.resource(['icons/loading.gif']), 'alt': _('Loading'), 'style': 'vertical-align:middle' }, _('Collecting data...')) ); var log; poll.add(L.bind(function() { return fs.read_direct(String.format('%s/%s.log', hp_dir, filename), 'text') .then(function(res) { log = E('pre', { 'wrap': 'pre' }, [ res.trim() || _('Log is empty.') ]); dom.content(log_textarea, log); }).catch(function(err) { if (err.toString().includes('NotFoundError')) log = E('pre', { 'wrap': 'pre' }, [ _('Log file does not exist.') ]); else log = E('pre', { 'wrap': 'pre' }, [ _('Unknown error: %s').format(err) ]); dom.content(log_textarea, log); }); })); return E([ E('style', [ css ]), E('div', {'class': 'cbi-map'}, [ E('h3', {'name': 'content'}, [ _('%s log').format(name), ' ', E('button', { 'class': 'btn cbi-button cbi-button-action', 'click': ui.createHandlerFn(this, function() { return L.resolveDefault(callLogClean(filename), {}); }) }, [ _('Clean log') ]) ]), E('div', {'class': 'cbi-section'}, [ log_textarea, E('div', {'style': 'text-align:right'}, E('small', {}, _('Refresh every %s seconds.').format(L.env.pollinterval)) ) ]) ]) ]); } return view.extend({ load: function() { return Promise.all([ uci.load('homeproxy') ]); }, render: function(data) { var m, s, o; var routing_mode = uci.get(data[0], 'config', 'routing_mode') || 'bypass_mainland_china'; m = new form.Map('homeproxy'); s = m.section(form.NamedSection, 'config', 'homeproxy', _('Connection check')); s.anonymous = true; o = s.option(form.DummyValue, '_check_baidu', _('BaiDu')); o.cfgvalue = function() { return getConnStat(this, 'baidu') }; o = s.option(form.DummyValue, '_check_google', _('Google')); o.cfgvalue = function() { return getConnStat(this, 'google') }; s = m.section(form.NamedSection, 'config', 'homeproxy', _('Resources management')); s.anonymous = true; o = s.option(form.DummyValue, '_china_ip4_version', _('China IPv4 list version')); o.cfgvalue = function() { return getResVersion(this, 'china_ip4') }; o.rawhtml = true; o = s.option(form.DummyValue, '_china_ip6_version', _('China IPv6 list version')); o.cfgvalue = function() { return getResVersion(this, 'china_ip6') }; o.rawhtml = true; o = s.option(form.DummyValue, '_china_list_version', _('China list version')); o.cfgvalue = function() { return getResVersion(this, 'china_list') }; o.rawhtml = true; o = s.option(form.DummyValue, '_gfw_list_version', _('GFW list version')); o.cfgvalue = function() { return getResVersion(this, 'gfw_list') }; o.rawhtml = true; s = m.section(form.NamedSection, 'config', 'homeproxy'); s.anonymous = true; o = s.option(form.DummyValue, '_homeproxy_logview'); o.render = L.bind(getRuntimeLog, this, _('HomeProxy'), 'homeproxy'); o = s.option(form.DummyValue, '_sing-box-c_logview'); o.render = L.bind(getRuntimeLog, this, _('sing-box client'), 'sing-box-c'); o = s.option(form.DummyValue, '_sing-box-s_logview'); o.render = L.bind(getRuntimeLog, this, _('sing-box server'), 'sing-box-s'); return m.render(); }, handleSaveApply: null, handleSave: null, handleReset: null });