update 2023-02-01 13:59:14
@ -67,7 +67,7 @@ plugins:
|
||||
- tag: cache
|
||||
type: cache
|
||||
args:
|
||||
size: cache_size
|
||||
size: 200000
|
||||
lazy_cache_ttl: 259200
|
||||
|
||||
# 转发至本地服务器
|
||||
|
@ -4,15 +4,14 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for UnblockNeteaseMusic (JavaScript)
|
||||
LUCI_DEPENDS:=+dnsmasq-full +node \
|
||||
+PACKAGE_firewall:ipset \
|
||||
LUCI_TITLE:=LuCI support for UnblockNeteaseMusic
|
||||
LUCI_DEPENDS:=+dnsmasq-full +ipset +node \
|
||||
@(PACKAGE_libustream-mbedtls||PACKAGE_libustream-openssl||PACKAGE_libustream-wolfssl)
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_NAME:=luci-app-unblockneteasemusic
|
||||
PKG_VERSION:=3.1
|
||||
PKG_RELEASE:=4
|
||||
PKG_VERSION:=2.13
|
||||
PKG_RELEASE:=6
|
||||
|
||||
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#进入 OpenWrt 源码 package 目录
|
||||
cd package
|
||||
#克隆插件源码
|
||||
git clone https://github.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic.git
|
||||
git clone --branch master https://github.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic.git
|
||||
#返回上一层目录
|
||||
cd ..
|
||||
#配置
|
||||
@ -42,10 +42,11 @@
|
||||
|
||||
### 效果图
|
||||
#### LuCI 界面
|
||||
![Image text](https://raw.githubusercontent.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic/js/views/view1.jpg)
|
||||
![Image text](https://raw.githubusercontent.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic/js/views/view2.jpg)
|
||||
![Image text](https://raw.githubusercontent.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic/master/views/view1.jpg)
|
||||
![Image text](https://raw.githubusercontent.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic/master/views/view2.jpg)
|
||||
![Image text](https://raw.githubusercontent.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic/master/views/view3.jpg)
|
||||
#### UWP 网易云音乐客户端
|
||||
![Image text](https://raw.githubusercontent.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic/js/views/view3.jpg)
|
||||
![Image text](https://raw.githubusercontent.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic/master/views/view4.jpg)
|
||||
|
||||
### 鸣谢
|
||||
[UnblockNeteaseMusic](https://github.com/UnblockNeteaseMusic/server)的开发者:[nondanee](https://github.com/nondanee)、[pan93412](https://github.com/pan93412)、[1715173329](https://github.com/1715173329)<br/>
|
||||
|
@ -1,334 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-only
|
||||
*
|
||||
* Copyright (C) 2022-2023 ImmortalWrt.org
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require network';
|
||||
'require poll';
|
||||
'require rpc';
|
||||
'require uci';
|
||||
'require ui';
|
||||
'require view';
|
||||
|
||||
var CBIStaticList = form.DynamicList.extend({
|
||||
__name__: 'CBI.StaticList',
|
||||
|
||||
renderWidget: function(/* ... */) {
|
||||
var dl = form.DynamicList.prototype.renderWidget.apply(this, arguments);
|
||||
dl.querySelector('.add-item ul > li[data-value="-"]').remove();
|
||||
return dl;
|
||||
}
|
||||
});
|
||||
|
||||
var callServiceList = rpc.declare({
|
||||
object: 'service',
|
||||
method: 'list',
|
||||
params: ['name'],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
function getServiceStatus() {
|
||||
return L.resolveDefault(callServiceList('unblockneteasemusic'), {}).then(function (res) {
|
||||
var isRunning = false;
|
||||
try {
|
||||
isRunning = res['unblockneteasemusic']['instances']['unblockneteasemusic']['running'];
|
||||
} catch (e) { }
|
||||
return isRunning;
|
||||
});
|
||||
}
|
||||
|
||||
function renderStatus(isRunning) {
|
||||
var spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
|
||||
var renderHTML;
|
||||
if (isRunning) {
|
||||
renderHTML = spanTemp.format('green', _('UnblockNeteaseMusic'), _('运行中'));
|
||||
} else {
|
||||
renderHTML = spanTemp.format('red', _('UnblockNeteaseMusic'), _('未运行'));
|
||||
}
|
||||
|
||||
return renderHTML;
|
||||
}
|
||||
|
||||
function uploadCertificate(type, filename, ev) {
|
||||
return ui.uploadFile('/usr/share/unblockneteasemusic/' + filename, ev.target)
|
||||
.then(L.bind(function(btn, res) {
|
||||
btn.firstChild.data = _('检查 %s 中...').format(type);
|
||||
|
||||
if (res.size <= 0) {
|
||||
ui.addNotification(null, E('p', _('上传的 %s 为空。').format(tyupe)));
|
||||
return fs.remove('/usr/share/unblockneteasemusic/' + filename);
|
||||
}
|
||||
|
||||
ui.addNotification(null, E('p', _('您的 %s 已成功上传。大小:%sB。').format(type, res.size)));
|
||||
}, this, ev.target))
|
||||
.catch(function(e) { ui.addNotification(null, E('p', e.message)) })
|
||||
.finally(L.bind(function(btn, input) {
|
||||
btn.firstChild.data = _('上传...');
|
||||
}, this, ev.target));
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
uci.load('unblockneteasemusic'),
|
||||
network.getHostHints()
|
||||
]);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var m, s, o;
|
||||
|
||||
m = new form.Map('unblockneteasemusic', _('解除网易云音乐播放限制'),
|
||||
_('原理:采用 [Bilibili/JOOX/酷狗/酷我/咪咕/pyncmd/QQ/Youtube] 等音源,替换网易云音乐 无版权/收费 歌曲链接<br/>' +
|
||||
'具体使用方法参见:<a href="https://github.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic" target="_blank">GitHub @UnblockNeteaseMusic/luci-app-unblockneteasemusic</a>'));
|
||||
|
||||
s = m.section(form.TypedSection);
|
||||
s.anonymous = true;
|
||||
s.render = function () {
|
||||
poll.add(function () {
|
||||
return L.resolveDefault(getServiceStatus()).then(function (res) {
|
||||
var view = document.getElementById('service_status');
|
||||
view.innerHTML = renderStatus(res);
|
||||
});
|
||||
});
|
||||
|
||||
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
|
||||
E('p', { id: 'service_status' }, _('收集数据中...'))
|
||||
]);
|
||||
}
|
||||
|
||||
s = m.section(form.NamedSection, 'config', 'unblockneteasemusic');
|
||||
|
||||
o = s.option(form.Flag, 'enable', _('启用服务'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(CBIStaticList, 'music_source', _('音源接口'),
|
||||
_('留空以使用默认音源。'));
|
||||
o.value('bilibili', _('Bilibili 音乐'));
|
||||
o.value('joox', _('JOOX 音乐'));
|
||||
o.value('kugou', _('酷狗音乐'));
|
||||
o.value('kuwo', _('酷我音乐'));
|
||||
o.value('migu', _('咪咕音乐'));
|
||||
o.value('pyncmd', _('网易云音乐(pyncmd)'));
|
||||
o.value('qq', _('QQ 音乐'));
|
||||
o.value('youtube', _('Youtube 音乐'));
|
||||
o.value('youtubedl', _('Youtube 音乐(youtube-dl)'));
|
||||
o.value('ytdlp', _('Youtube 音乐(yt-dlp)'));
|
||||
o.value('ytdownload', _('Youtube 音乐(ytdownload)'));
|
||||
|
||||
o = s.option(form.Value, 'joox_cookie', _('JOOX Cookie'),
|
||||
_('在 joox.com 获取,需要 wmid 和 session_key 值。'));
|
||||
o.placeholder = 'wmid=; session_key=';
|
||||
o.rmempty = false;
|
||||
o.depends({'music_source': 'joox', '!contains': true});
|
||||
|
||||
o = s.option(form.Value, 'migu_cookie', _('Migu Cookie'),
|
||||
_('通过抓包手机客户端请求获取,需要 aversionid 值。'));
|
||||
o.depends({'music_source': 'migu', '!contains': true});
|
||||
|
||||
o = s.option(form.Value, 'qq_cookie', _('QQ Cookie'),
|
||||
_('在 y.qq.com 获取,需要 uin 和 qm_keyst 值。'));
|
||||
o.placeholder = 'uin=; qm_keyst=';
|
||||
o.rmempty = false;
|
||||
o.depends({'music_source': 'qq', '!contains': true});
|
||||
|
||||
o = s.option(form.Value, 'youtube_key', _('Youtube API Key'),
|
||||
_('API Key 申请地址:https://developers.google.com/youtube/v3/getting-started#before-you-start'));
|
||||
o.depends({'music_source': 'youtube', '!contains': true});
|
||||
|
||||
o = s.option(form.Flag, 'follow_source_order', _('顺序查询'),
|
||||
_('默认为并行查询并返回第一个结果,开启后将严格按照配置音源的顺序进行查询。'))
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.Flag, 'search_album', _('附加专辑名'),
|
||||
_('在其他音源搜索歌曲时携带专辑名称(默认搜索条件 <code>歌曲名 - 歌手</code>,启用后搜索条件 <code>歌曲名 - 歌手 专辑名</code>)。'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.Flag, 'enable_flac', _('启用无损音质'),
|
||||
_('目前仅支持酷狗、酷我、咪咕、pyncmd、QQ 音源。'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.Flag, 'select_max_br', _('选取最高音质'),
|
||||
_('选择所有音源中的最高码率替换音频。'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.ListValue, 'replace_music_source', _('音源替换'),
|
||||
_('当源音乐音质低于指定数值时,尝试强制使用其他平台的高音质版本进行替换。'));
|
||||
o.value('dont_replace', _('不强制替换音乐音源'));
|
||||
o.value('lower_than_192kbps', _('当音质低于 192 Kbps(中)时'));
|
||||
o.value('lower_than_320kbps', _('当音质低于 320 Kbps(高)时'));
|
||||
o.value('lower_than_999kbps', _('当音质低于 999 Kbps(无损)时'));
|
||||
o.value('replace_all', _('替换所有音乐音源'));
|
||||
o.default = 'dont_replace';
|
||||
|
||||
o = s.option(form.Flag, 'disable_upgrade_check', _('禁用更新检查'),
|
||||
_('拦截网易云音乐客户端更新请求,全平台支持。'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.Flag, 'block_ads', _('屏蔽广告'),
|
||||
('启用后,可屏蔽应用内<strong>部分</strong>广告。'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.Flag, 'local_vip', _('启用本地 VIP'),
|
||||
_('启用后,可以使用去广告、个性换肤、鲸云音效等本地功能。'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.Flag, 'auto_update', _('启用自动更新'),
|
||||
_('启用后,每天将定时自动检查最新核心版本并更新。'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.option(form.ListValue, 'update_time', '检查更新时间',
|
||||
_('设定每天自动检查更新时间。'));
|
||||
for (var i = 0; i < 24; i++)
|
||||
o.value(i, i + ':00');
|
||||
o.default = '3';
|
||||
o.depends('auto_update', '1');
|
||||
|
||||
o = s.option(form.Button, '_download_cert', _('CA 根证书'),
|
||||
_('Linux / iOS / MacOSX 在信任根证书后方可正常使用。'));
|
||||
o.inputstyle = 'apply';
|
||||
o.inputtitle = _('下载 ca.crt');
|
||||
o.onclick = function() {
|
||||
return fs.read_direct('/usr/share/unblockneteasemusic/core/ca.crt', 'blob').then(function(blob) {
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
var link = E('a', { 'style': 'display:none', 'href': url, 'download': 'ca.crt' });
|
||||
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}).catch(function(err) {
|
||||
ui.addNotification(null, E('p', [ _('下载文件失败:%s。').format(err.message) ]));
|
||||
});
|
||||
}
|
||||
|
||||
o = s.option(form.Flag, 'advanced_mode', _('启用进阶设置'),
|
||||
_('非必要不推荐启用。'));
|
||||
o.default = o.disabled,
|
||||
|
||||
o = s.option(form.ListValue, 'log_level', _('日志等级'));
|
||||
o.value('debug', _('调试'));
|
||||
o.value('info', _('信息(默认)'));
|
||||
o.value('silent', _('静默'));
|
||||
o.default = 'info';
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Value, 'http_port', _('HTTP 监听端口'));
|
||||
o.datatype = 'port';
|
||||
o.default = '5200';
|
||||
o.rmempty = false;
|
||||
o.depends('hijack_ways', 'dont_hijack');
|
||||
o.depends('hijack_ways', 'use_ipset');
|
||||
|
||||
o = s.option(form.Value, 'https_port', _('HTTPS 监听端口'));
|
||||
o.datatype = 'port';
|
||||
o.default = '5201';
|
||||
o.rmempty = false;
|
||||
o.depends('hijack_ways', 'dont_hijack');
|
||||
o.depends('hijack_ways', 'use_ipset');
|
||||
|
||||
o = s.option(form.Value, 'endpoint_url', _('EndPoint'),
|
||||
_('音源地址反代(包装)。'));
|
||||
o.default = 'https://music.163.com';
|
||||
o.rmempty = false;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Value, 'cnrelay', _('UNM Bridge 服务器'),
|
||||
_('使用 UnblockNeteaseMusic 中继桥(bridge)以获取音源信息。'));
|
||||
o.placeholder = 'http(s)://host:port'
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.ListValue, 'hijack_ways', _('劫持方法'),
|
||||
_('如果使用 Hosts 劫持,监听端口将固定为 80/443,请注意更改您的 webUI 端口。'));
|
||||
o.value('dont_hijack', _('不开启劫持'));
|
||||
o.value('use_ipset', _('使用 IPSet 劫持'));
|
||||
o.value('use_hosts', _('使用 Hosts 劫持'));
|
||||
o.default = 'dont_hijack';
|
||||
o.rmempty = false;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Flag, 'keep_core_when_upgrade', _('升级时保留核心程序'));
|
||||
o.default = o.disabled;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Flag, 'pub_access', _('部署到公网'),
|
||||
_('默认仅放行局域网请求,如需提供公开访问请勾选此选项。'));
|
||||
o.default = o.disabled;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Flag, 'strict_mode', _('启用严格模式'),
|
||||
_('若将服务部署到公网,则强烈建议使用严格模式,此模式下仅放行网易云音乐所属域名的请求。<br/>注意:该模式下不能使用全局代理。'));
|
||||
o.default = o.disabled;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Value, 'netease_server_ip', _('网易云服务器 IP'));
|
||||
o.datatype = 'ipaddr';
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Value, 'proxy_server_ip', _('代理服务器地址'),
|
||||
_('使用代理服务器获取音乐信息。'));
|
||||
o.placeholder = 'http(s)://host:port';
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Value, 'self_issue_cert_crt', _('自签发证书公钥位置'));
|
||||
o.value('/usr/share/unblockneteasemusic/core/server.crt', _('内置公钥'));
|
||||
o.value('/usr/share/unblockneteasemusic/server.crt');
|
||||
o.default = '/usr/share/unblockneteasemusic/core/server.crt';
|
||||
o.datatype = 'file';
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Button, '_upload_cert', _('上传公钥'));
|
||||
o.inputstyle = 'action';
|
||||
o.inputtitle = _('上传...');
|
||||
o.depends('self_issue_cert_crt', '/usr/share/unblockneteasemusic/server.crt');
|
||||
o.onclick = L.bind(uploadCertificate, this, _('公钥'), 'server.crt');
|
||||
o.modalonly = true;
|
||||
|
||||
o = s.option(form.Value, 'self_issue_cert_key', _('自签发证书私钥位置'));
|
||||
o.value('/usr/share/unblockneteasemusic/core/server.key', _('内置私钥'));
|
||||
o.value('/usr/share/unblockneteasemusic/server.key');
|
||||
o.default = '/usr/share/unblockneteasemusic/core/server.key';
|
||||
o.datatype = 'file'
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Button, '_upload_key', _('上传私钥'));
|
||||
o.inputstyle = 'action';
|
||||
o.inputtitle = _('上传...');
|
||||
o.depends('self_issue_cert_key', '/usr/share/unblockneteasemusic/server.key');
|
||||
o.onclick = L.bind(uploadCertificate, this, _('私钥'), 'server.key');
|
||||
o.modalonly = true;
|
||||
|
||||
s = m.section(form.TableSection, 'acl_rule', _('例外客户端规则'),
|
||||
_('可以为局域网客户端分别设置不同的例外模式。'));
|
||||
s.addremove = true;
|
||||
s.anonymous = true;
|
||||
s.sortable = true;
|
||||
|
||||
o = s.option(form.Flag, 'enable', _('启用'));
|
||||
o.default = o.enabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Value, 'ip_addr', _('IP 地址'));
|
||||
o.datatype = 'ip4addr';
|
||||
for (var i of Object.entries(data[1].hosts))
|
||||
for (var v in i[1].ipaddrs)
|
||||
if (i[1].ipaddrs[v]) {
|
||||
var ip_addr = i[1].ipaddrs[v], ip_host = i[1].name;
|
||||
o.value(ip_addr, ip_host ? String.format('%s (%s)', ip_host, ip_addr) : ip_addr)
|
||||
}
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.ListValue, 'filter_mode', _('规则'));
|
||||
o.value('disable_all', _('不代理 HTTP 和 HTTPS'));
|
||||
o.value('disable_http', _('不代理 HTTP'));
|
||||
o.value('disable_https', _('不代理 HTTPS'));
|
||||
o.default = 'disable_all';
|
||||
o.rmempty = false;
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
@ -1,224 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-only
|
||||
*
|
||||
* Copyright (C) 2022 ImmortalWrt.org
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
'require dom';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require poll';
|
||||
'require rpc';
|
||||
'require ui';
|
||||
'require view';
|
||||
|
||||
return view.extend({
|
||||
render: function() {
|
||||
var m, s, o;
|
||||
|
||||
var unm_helper = '/usr/share/unblockneteasemusic/update.sh';
|
||||
|
||||
m = new form.Map('unblockneteasemusic');
|
||||
|
||||
s = m.section(form.NamedSection, 'config', 'unblockneteasemusic', _('核心管理'));
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.DummyValue, '_core_version', _('核心版本'));
|
||||
o.cfgvalue = function() {
|
||||
var _this = this;
|
||||
var spanTemp = '<div style="color:%s;margin-top:5px;"><strong>%s</strong></div>';
|
||||
|
||||
return fs.exec(unm_helper, [ 'check_version' ]).then(function(res) {
|
||||
if (res.code === 0)
|
||||
_this.default = String.format(spanTemp, 'green', res.stdout.trim());
|
||||
else if (res.code === 2)
|
||||
_this.default = String.format(spanTemp, 'red', _('未安装'));
|
||||
else {
|
||||
ui.addNotification(null, E('p', [ _('获取版本信息失败:%s。').format(res) ]));
|
||||
_this.default = String.format(spanTemp, 'red', _('未知错误'));
|
||||
}
|
||||
|
||||
return null;
|
||||
}).catch(function(err) {
|
||||
ui.addNotification(null, E('p', [ _('未知错误:%s。').format(err) ]));
|
||||
_this.default = String.format(spanTemp, 'red', _('未知错误'));
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
o.rawhtml = true;
|
||||
|
||||
o = s.option(form.Button, '_remove_core', _('删除核心'),
|
||||
_('删除核心后,需手动点击下面的按钮重新下载,有助于解决版本冲突问题。'));
|
||||
o.inputstyle = 'remove';
|
||||
o.onclick = function() {
|
||||
var _this = this;
|
||||
|
||||
return fs.exec(unm_helper, [ 'remove_core' ]).then(function(res) {
|
||||
_this.description = '删除完毕。'
|
||||
return _this.map.reset();
|
||||
}).catch(function(err) {
|
||||
ui.addNotification(null, E('p', [ _('未知错误:%s。').format(err) ]));
|
||||
_this.description = '删除失败。'
|
||||
return _this.map.reset();
|
||||
});
|
||||
}
|
||||
|
||||
o = s.option(form.Button, '_update_core', _('更新核心'),
|
||||
_('更新完毕后会自动在后台重启插件,无需手动重启。'));
|
||||
o.inputstyle = 'action';
|
||||
o.onclick = function() {
|
||||
var _this = this;
|
||||
|
||||
return fs.exec(unm_helper, [ 'update_core' ]).then(function (res) {
|
||||
if (res.code === 0)
|
||||
_this.description = _('更新成功。');
|
||||
else if (res.code === 1)
|
||||
_this.description = _('更新失败。');
|
||||
else if (res.code === 2)
|
||||
_this.description = _('更新程序正在运行中。');
|
||||
else if (res.code === 3)
|
||||
_this.description = _('当前已是最新版本。');
|
||||
|
||||
return _this.map.reset();
|
||||
}).catch(function (err) {
|
||||
ui.addNotification(null, E('p', [ _('未知错误:%s。').format(err) ]));
|
||||
_this.description = _('更新失败。');
|
||||
return _this.map.reset();
|
||||
});
|
||||
}
|
||||
|
||||
o = s.option(form.Button, '_debug_log', _('调试报告'),
|
||||
_('若您遇到使用上的问题,请点此打印调试报告,并将其附在您的 issue 中。'));
|
||||
o.inputstyle = 'action';
|
||||
o.inputtitle = _('打印报告');
|
||||
o.onclick = function() {
|
||||
var log_modal = ui.showModal(_('打印调试报告'), [
|
||||
E('p', { 'class': 'spinning' },
|
||||
_('正在打印调试报告中...'))
|
||||
]);
|
||||
|
||||
return fs.exec_direct('/usr/bin/unm-debug', 'text').then(function (res) {
|
||||
log_modal.removeChild(log_modal.lastChild);
|
||||
|
||||
if (res) {
|
||||
log_modal.appendChild(E('p', _('提交 issue 时,您只需附上最后的链接,无需提供整个输出。')));
|
||||
log_modal.appendChild(E('textarea', {
|
||||
'id': 'content_debugLog',
|
||||
'class': 'cbi-input-textarea',
|
||||
'style': 'font-size:13px; resize: none',
|
||||
'readonly': 'readonly',
|
||||
'wrap': 'soft',
|
||||
'rows': '30'
|
||||
}, [ res.trim() ])
|
||||
);
|
||||
} else {
|
||||
log_modal.appendChild(E('p', _('错误')));
|
||||
log_modal.appendChild(E('pre', { 'class': 'errors' }, [ _('无法打印调试报告。') ]));
|
||||
}
|
||||
|
||||
var log_element = document.getElementById('content_debugLog') || null;
|
||||
if (log_element)
|
||||
log_element.scrollTop = log_element.scrollHeight;
|
||||
|
||||
log_modal.appendChild(E('div', { 'class': 'right' }, [
|
||||
log_element ? E('button', {
|
||||
'class': 'btn cbi-button-action',
|
||||
'click': ui.createHandlerFn(this, function() {
|
||||
var links = log_element.value.match(/https:\/\/(litter.catbox.moe|transfer.sh)\/.*.txt/g);
|
||||
|
||||
var textarea = document.createElement('textarea');
|
||||
document.body.appendChild(textarea);
|
||||
|
||||
textarea.style.position = 'absolute';
|
||||
textarea.style.clip = 'rect(0 0 0 0)';
|
||||
textarea.value = links ? links.join('\n'): log_element.value;
|
||||
textarea.select()
|
||||
|
||||
document.execCommand('copy', true);
|
||||
document.body.removeChild(textarea);
|
||||
})
|
||||
}, _('复制')) : '',
|
||||
E('button', {
|
||||
'class': 'btn',
|
||||
'click': ui.hideModal
|
||||
}, _('关闭'))
|
||||
]));
|
||||
|
||||
return null;
|
||||
}).catch(function (err) {
|
||||
ui.addNotification(null, E('p', _('无法打印调试报告:%s。').format(err)));
|
||||
ui.hideModal();
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
o = s.option(form.DummyValue, '_logview');
|
||||
o.render = function() {
|
||||
/* 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 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(L.bind(function() {
|
||||
return fs.read('/tmp/unblockneteasemusic.log', 'text')
|
||||
.then(function(res) {
|
||||
var log = E('pre', { 'wrap': 'pre' }, [
|
||||
res.trim() || _('当前无日志。')
|
||||
]);
|
||||
|
||||
dom.content(log_textarea, log);
|
||||
}).catch(function(err) {
|
||||
if (err.toString().includes('NotFoundError'))
|
||||
var log = E('pre', { 'wrap': 'pre' }, [
|
||||
_('日志文件不存在。')
|
||||
]);
|
||||
else
|
||||
var log = E('pre', { 'wrap': 'pre' }, [
|
||||
_('未知错误:%s。').format(err)
|
||||
]);
|
||||
|
||||
dom.content(log_textarea, log);
|
||||
});
|
||||
}));
|
||||
|
||||
return E([
|
||||
E('style', [ css ]),
|
||||
E('div', {'class': 'cbi-map'}, [
|
||||
E('h3', {'name': 'content'}, _('运行日志')),
|
||||
E('div', {'class': 'cbi-section'}, [
|
||||
log_textarea,
|
||||
E('div', {'style': 'text-align:right'},
|
||||
E('small', {}, _('每 %s 秒刷新。').format(L.env.pollinterval))
|
||||
)
|
||||
])
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
return m.render();
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
});
|
@ -0,0 +1,69 @@
|
||||
-- SPDX-License-Identifer: GPL-3.0-only
|
||||
-- Copyright (C) 2019-2022 Tianling Shen <cnsztl@immortalwrt.org>
|
||||
|
||||
module("luci.controller.unblockneteasemusic", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/unblockneteasemusic") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
page = entry({"admin", "services", "unblockneteasemusic"}, firstchild(), _("解除网易云音乐播放限制"), 50)
|
||||
page.dependent = false
|
||||
page.acl_depends = { "luci-app-unblockneteasemusic" }
|
||||
|
||||
entry({"admin", "services", "unblockneteasemusic", "general"}, cbi("unblockneteasemusic/main"), _("基本设定"), 1)
|
||||
entry({"admin", "services", "unblockneteasemusic", "upgrade"}, form("unblockneteasemusic/upgrade"), _("更新组件"), 2).leaf = true
|
||||
entry({"admin", "services", "unblockneteasemusic", "log"}, form("unblockneteasemusic/log"), _("日志"), 3)
|
||||
|
||||
entry({"admin", "services", "unblockneteasemusic", "status"}, call("act_status")).leaf = true
|
||||
entry({"admin", "services", "unblockneteasemusic", "update_core"}, call("act_update_core"))
|
||||
entry({"admin", "services", "unblockneteasemusic", "remove_core"}, call("act_remove_core"))
|
||||
end
|
||||
|
||||
function act_status()
|
||||
local stat = luci.util.ubus("service", "list", { name = "unblockneteasemusic" })
|
||||
local running = next(stat) and next(stat.unblockneteasemusic) and stat.unblockneteasemusic.instances.unblockneteasemusic.running or false
|
||||
|
||||
local e = { running = running }
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
|
||||
function update_core()
|
||||
local core_cloud_ver = luci.sys.exec("uclient-fetch -qO- 'https://api.github.com/repos/UnblockNeteaseMusic/server/commits?sha=enhanced&path=precompiled' | jsonfilter -e '@[0].sha'")
|
||||
local core_cloud_ver_mini = string.sub(core_cloud_ver, 1, 7)
|
||||
local core_local_ver
|
||||
if not core_cloud_ver or not core_cloud_ver_mini then
|
||||
return "1"
|
||||
else
|
||||
core_local_ver = luci.sys.exec("cat '/usr/share/unblockneteasemusic/core_local_ver' 2>'/dev/null'")
|
||||
if not core_local_ver or (core_local_ver ~= core_cloud_ver) then
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_core_successfully")
|
||||
luci.sys.call("/usr/share/unblockneteasemusic/update.sh update_core_from_luci")
|
||||
if not nixio.fs.access("/usr/share/unblockneteasemusic/update_core_successfully") then
|
||||
return "2"
|
||||
else
|
||||
luci.sys.call("rm -f /usr/share/unblockneteasemusic/update_core_successfully")
|
||||
return core_cloud_ver_mini
|
||||
end
|
||||
else
|
||||
return "0"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function act_update_core()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
ret = update_core();
|
||||
})
|
||||
end
|
||||
|
||||
function act_remove_core()
|
||||
local ret = {}
|
||||
ret.ret = luci.sys.call("cd /usr/share/unblockneteasemusic && rm -rf core/* && rm -f core_local_ver") == 0
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(ret)
|
||||
end
|
@ -0,0 +1,14 @@
|
||||
local fs = require "nixio.fs"
|
||||
local conffile = "/tmp/unblockneteasemusic.log"
|
||||
|
||||
f = SimpleForm("logview")
|
||||
|
||||
t = f:field(TextValue, "conf")
|
||||
t.rmempty = true
|
||||
t.rows = 15
|
||||
function t.cfgvalue()
|
||||
return fs.readfile(conffile) or ""
|
||||
end
|
||||
t.readonly="readonly"
|
||||
|
||||
return f
|
@ -0,0 +1,247 @@
|
||||
local m, s, o
|
||||
|
||||
m = Map("unblockneteasemusic", translate("解除网易云音乐播放限制"))
|
||||
m.description = translate("原理:采用 [Bilibili/JOOX/酷狗/酷我/咪咕/pyncmd/QQ/Youtube] 等音源,替换网易云音乐 无版权/收费 歌曲链接<br/>具体使用方法参见:<a href=\"https://github.com/UnblockNeteaseMusic/luci-app-unblockneteasemusic\" target=\"_blank\">GitHub @UnblockNeteaseMusic/luci-app-unblockneteasemusic</a>")
|
||||
|
||||
m:section(SimpleSection).template = "unblockneteasemusic/status"
|
||||
|
||||
s = m:section(NamedSection, "config", "unblockneteasemusic")
|
||||
|
||||
o = s:option(Flag, "enable", translate("启用本插件"))
|
||||
o.description = translate("启用本插件以解除网易云音乐播放限制")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "music_source", translate("音源接口"))
|
||||
o:value("default", translate("默认"))
|
||||
o:value("bilibili", translate("Bilibili音乐"))
|
||||
o:value("joox", translate("JOOX音乐"))
|
||||
o:value("kugou", translate("酷狗音乐"))
|
||||
o:value("kuwo", translate("酷我音乐"))
|
||||
o:value("migu", translate("咪咕音乐"))
|
||||
o:value("pyncmd", translate("网易云音乐(pyncmd)"))
|
||||
o:value("qq", translate("QQ音乐"))
|
||||
o:value("youtube", translate("Youtube音乐"))
|
||||
o:value("youtubedl", translate("Youtube音乐(youtube-dl)"))
|
||||
o:value("ytdlp", translate("Youtube音乐(yt-dlp)"))
|
||||
o:value("ytdownload", translate("Youtube音乐(ytdownload)"))
|
||||
o.description = translate("自定义模式下,多个音源请用空格隔开")
|
||||
o.default = "default"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "follow_source_order", translate("顺序查询"))
|
||||
o.description = translate("默认为并行查询并返回第一个结果,开启后将严格按照配置音源的顺序进行查询")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "search_album", translate("附加专辑名"))
|
||||
o.description = translate("在其他音源搜索歌曲时携带专辑名称(默认搜索条件 歌曲名 - 歌手,启用后搜索条件 歌曲名 - 歌手 专辑名)")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "local_vip", translate("启用本地 VIP"))
|
||||
o.description = translate("启用后,可以使用去广告、个性换肤、鲸云音效等本地功能")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "enable_flac", translate("启用无损音质"))
|
||||
o.description = translate("目前仅支持酷狗、酷我、咪咕、pyncmd、QQ 音源")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "disable_upgrade_check", translate("禁用更新检查"))
|
||||
o.description = translate("禁止客户端检查更新,全平台支持")
|
||||
o.default = 1
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "replace_music_source", translate("强制音乐音源替换"))
|
||||
o:value("dont_replace", translate("不强制替换音乐音源"))
|
||||
o:value("lower_than_192kbps", translate("当音质低于 192 Kbps(中)时"))
|
||||
o:value("lower_than_320kbps", translate("当音质低于 320 Kbps(高)时"))
|
||||
o:value("lower_than_999kbps", translate("当音质低于 999 Kbps(无损)时"))
|
||||
o:value("replace_all", translate("替换所有音乐音源"))
|
||||
o.description = translate("当音乐音质低于指定数值时,尝试强制使用其他平台的高音质版本进行替换")
|
||||
o.default = "dont_replace"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "use_custom_cookie", translate("使用自定义 Cookie"))
|
||||
o.description = translate("使用自定义 Cookie 请求音源接口")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "joox_cookie", translate("JOOX Cookie"))
|
||||
o.description = translate("在 joox.com 获取,需要 wmid 和 session_key 值")
|
||||
o.placeholder = "wmid=; session_key="
|
||||
o.datatype = "string"
|
||||
o:depends("use_custom_cookie", 1)
|
||||
|
||||
o = s:option(Value, "migu_cookie", translate("Migu Cookie"))
|
||||
o.description = translate("通过抓包手机客户端请求获取,需要 aversionid 值")
|
||||
o.datatype = "string"
|
||||
o:depends("use_custom_cookie", 1)
|
||||
|
||||
o = s:option(Value, "qq_cookie", translate("QQ Cookie"))
|
||||
o.description = translate("在 y.qq.com 获取,需要 uin 和 qm_keyst值 ")
|
||||
o.placeholder = "uin=; qm_keyst="
|
||||
o.datatype = "string"
|
||||
o:depends("use_custom_cookie", 1)
|
||||
|
||||
o = s:option(Value, "youtube_key", translate("Youtube API Key"))
|
||||
o.description = translate("API Key 申请地址:https://developers.google.com/youtube/v3/getting-started#before-you-start")
|
||||
o.datatype = "string"
|
||||
o:depends("use_custom_cookie", 1)
|
||||
|
||||
o = s:option(Flag, "auto_update", translate("启用自动更新"))
|
||||
o.description = translate("启用后,每天将定时自动检查最新版本并更新")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "update_time", translate("检查更新时间"))
|
||||
for update_time_hour = 0,23 do
|
||||
o:value(update_time_hour, update_time_hour..":00")
|
||||
end
|
||||
o.default = "3"
|
||||
o.description = translate("设定每天自动检查更新时间")
|
||||
o:depends("auto_update", 1)
|
||||
|
||||
o = s:option(Button,"certificate", translate("HTTPS 证书"))
|
||||
o.inputtitle = translate("下载 CA 根证书")
|
||||
o.description = translate("Linux/iOS/MacOSX 在信任根证书后方可正常使用")
|
||||
o.inputstyle = "reload"
|
||||
o.write = function()
|
||||
act_download_cert()
|
||||
end
|
||||
|
||||
function act_download_cert()
|
||||
local t, e
|
||||
t = nixio.open("/usr/share/unblockneteasemusic/core/ca.crt","r")
|
||||
luci.http.header('Content-Disposition', 'attachment; filename="ca.crt"')
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
while true do
|
||||
e = t:read(nixio.const.buffersize)
|
||||
if (not e) or (#e == 0) then
|
||||
break
|
||||
else
|
||||
luci.http.write(e)
|
||||
end
|
||||
end
|
||||
t:close()
|
||||
luci.http.close()
|
||||
end
|
||||
|
||||
o = s:option(Flag, "advanced_mode", translate("启用进阶设置"))
|
||||
o.description = translate("非必要不推荐使用")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "log_level", translate("日志等级"))
|
||||
o:value("debug", translate("'调试"));
|
||||
o:value("info", translate("信息(默认)"))
|
||||
o:value("silent", translate("静默"))
|
||||
o.default = "info";
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Value, "http_port", translate("HTTP 监听端口"))
|
||||
o.description = translate("程序监听的 HTTP 端口,不可与 其他程序/HTTPS 共用一个端口")
|
||||
o.placeholder = "5200"
|
||||
o.default = "5200"
|
||||
o.datatype = "port"
|
||||
o:depends({advanced_mode = true, hijack_ways = "dont_hijack"})
|
||||
o:depends({advanced_mode = true, hijack_ways = "use_ipset"})
|
||||
|
||||
o = s:option(Value, "https_port", translate("HTTPS 监听端口"))
|
||||
o.description = translate("程序监听的 HTTPS 端口,不可与 其他程序/HTTP 共用一个端口")
|
||||
o.placeholder = "5201"
|
||||
o.default = "5201"
|
||||
o.datatype = "port"
|
||||
o:depends({advanced_mode = true, hijack_ways = "dont_hijack"})
|
||||
o:depends({advanced_mode = true, hijack_ways = "use_ipset"})
|
||||
|
||||
o = s:option(Value, "endpoint_url", translate("EndPoint"))
|
||||
o.description = translate("具体说明参见:https://github.com/UnblockNeteaseMusic/server")
|
||||
o.default = "https://music.163.com"
|
||||
o.placeholder = "https://music.163.com"
|
||||
o.datatype = "string"
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Value, "cnrelay", translate("UNM bridge 服务器"))
|
||||
o.description = translate("使用 UnblockNeteaseMusic 中继桥(bridge)以获取音源信息")
|
||||
o.placeholder = "http(s)://host:port"
|
||||
o.datatype = "string"
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(ListValue, "hijack_ways", translate("劫持方法"))
|
||||
o:value("dont_hijack", translate("不开启劫持"))
|
||||
o:value("use_ipset", translate("使用 IPSet 劫持"))
|
||||
o:value("use_hosts", translate("使用 Hosts 劫持"))
|
||||
o.description = translate("如果使用Hosts劫持,程序监听的 HTTP/HTTPS 端口将被锁定为 80/443")
|
||||
o.default = "dont_hijack"
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Flag, "keep_core_when_upgrade", translate("升级时保留核心程序"))
|
||||
o.description = translate("默认情况下,在系统升级后会导致核心程序丢失,开启此选项后会保留当前下载的核心程序")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Flag, "pub_access", translate("部署到公网"))
|
||||
o.description = translate("默认仅监听局域网,如需提供公开访问请勾选此选项")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Flag, "strict_mode", translate("启用严格模式"))
|
||||
o.description = translate("若将服务部署到公网,则强烈建议使用严格模式,此模式下仅放行网易云音乐所属域名的请求;注意:该模式下不能使用全局代理")
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Value, "netease_server_ip", translate("网易云服务器 IP"))
|
||||
o.description = translate("通过 ping music.163.com 即可获得 IP 地址,仅限填写一个")
|
||||
o.placeholder = "59.111.181.38"
|
||||
o.datatype = "ipaddr"
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Value, "proxy_server_ip", translate("代理服务器地址"))
|
||||
o.description = translate("使用代理服务器获取音乐信息")
|
||||
o.placeholder = "http(s)://host:port"
|
||||
o.datatype = "string"
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Value, "self_issue_cert_crt", translate("自签发证书公钥位置"))
|
||||
o.description = translate("[公钥] 默认使用 UnblockNeteaseMusic 项目提供的 CA 证书,您可以指定为您自己的证书")
|
||||
o.placeholder = "/usr/share/unblockneteasemusic/core/server.crt"
|
||||
o.datatype = "file"
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
o = s:option(Value, "self_issue_cert_key", translate("自签发证书私钥位置"))
|
||||
o.description = translate("[私钥] 默认使用 UnblockNeteaseMusic 项目提供的 CA 证书,您可以指定为您自己的证书")
|
||||
o.placeholder = "/usr/share/unblockneteasemusic/core/server.key"
|
||||
o.datatype = "file"
|
||||
o:depends("advanced_mode", 1)
|
||||
|
||||
s = m:section(TypedSection, "acl_rule", translate("例外客户端规则"), translate("可以为局域网客户端分别设置不同的例外模式,默认无需设置"))
|
||||
s.template = "cbi/tblsection"
|
||||
s.sortable = true
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
o = s:option(Value, "ip_addr", translate("IP 地址"))
|
||||
o.width = "40%"
|
||||
o.datatype = "ip4addr"
|
||||
o.placeholder = "0.0.0.0/0"
|
||||
luci.ip.neighbors({ family = 4 }, function(entry)
|
||||
if entry.reachable then
|
||||
o:value(entry.dest:string())
|
||||
end
|
||||
end)
|
||||
|
||||
o = s:option(ListValue, "filter_mode", translate("规则"))
|
||||
o.width = "40%"
|
||||
o.default = "disable_all"
|
||||
o.rmempty = false
|
||||
o:value("disable_all", translate("不代理 HTTP 和 HTTPS"))
|
||||
o:value("disable_http", translate("不代理 HTTP"))
|
||||
o:value("disable_https", translate("不代理 HTTPS"))
|
||||
|
||||
return m
|
@ -0,0 +1,19 @@
|
||||
local m, o
|
||||
|
||||
m = SimpleForm("Version")
|
||||
m.reset = false
|
||||
m.submit = false
|
||||
|
||||
o = m:field(DummyValue, "remove_core", translate("删除核心"))
|
||||
o.rawhtml = true
|
||||
o.template = "unblockneteasemusic/remove_core"
|
||||
o.value = translate("")
|
||||
o.description = "删除核心后,需手动点击下面的按钮重新下载,有助于解决版本冲突问题"
|
||||
|
||||
o = m:field(DummyValue, "update_core", translate("更新核心"))
|
||||
o.rawhtml = true
|
||||
o.template = "unblockneteasemusic/update_core"
|
||||
o.value = translate("")
|
||||
o.description = "更新完毕后会自动在后台重启插件,无需手动重启"
|
||||
|
||||
return m
|
@ -0,0 +1,32 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function act_remove_core(btn, dataname)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:正在删除核心...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "unblockneteasemusic", "remove_core")%>',
|
||||
status.ret,
|
||||
function(x, status)
|
||||
{
|
||||
var s = document.getElementById(dataname + '-status');
|
||||
if (s)
|
||||
{
|
||||
if(status.ret)
|
||||
s.innerHTML = "<font style=\"color:green\">" + "<%:删除核心成功%>" + "</font>";
|
||||
else
|
||||
s.innerHTML = "<font style=\"color:red\">" + "<%:删除核心失败%>"+"</font>";
|
||||
}
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:点此删除核心%>';
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
|
||||
<input type="button" class="btn cbi-button cbi-input-reload" value="<%:点此删除核心%>" onclick="return act_remove_core(this, '<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
@ -0,0 +1,21 @@
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(3, '<%=url([[admin]], [[services]], [[unblockneteasemusic]], [[status]])%>', null,
|
||||
function(x, data) {
|
||||
var tb = document.getElementById('unblockneteasemusic_status');
|
||||
if (data && tb) {
|
||||
if (data.running) {
|
||||
tb.innerHTML = '<em><b style=color:green>UnblockNeteaseMusic <%:运行中%></b></em>';
|
||||
} else {
|
||||
tb.innerHTML = '<em><b style=color:red>UnblockNeteaseMusic <%:未在运行%></b></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]>
|
||||
</script>
|
||||
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
|
||||
<fieldset class="cbi-section">
|
||||
<p id="unblockneteasemusic_status">
|
||||
<em><%:Collecting data...%></em>
|
||||
</p>
|
||||
</fieldset>
|
@ -0,0 +1,36 @@
|
||||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function act_update_core(btn, dataname)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:正在更新核心...%>';
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "unblockneteasemusic", "update_core")%>',
|
||||
status.ret,
|
||||
function(x, status)
|
||||
{
|
||||
var s = document.getElementById(dataname + '-status');
|
||||
if (s)
|
||||
{
|
||||
if(status.ret == "0")
|
||||
s.innerHTML = "<font style=\"color:green\">" + "<%:当前已是最新版本%>" + "</font>";
|
||||
else if (status.ret == "1")
|
||||
s.innerHTML = "<font style=\"color:red\">" + "<%:无法检测最新版本%>" + "</font>";
|
||||
else if(status.ret == "2")
|
||||
s.innerHTML = "<font style=\"color:red\">" + "<%:更新失败,请稍后重试%>" + "</font>";
|
||||
else
|
||||
s.innerHTML = "<font style=\"color:green\">" + "<%:更新成功,当前版本号:%>" + status.ret + "</font>";
|
||||
}
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:点此更新核心%>';
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
|
||||
<input type="button" class="btn cbi-button cbi-input-reload" value="<%:点此更新核心%>" onclick="return act_update_core(this, '<%=self.option%>')" />
|
||||
<span id="<%=self.option%>-status"><em><%=self.value%></em></span>
|
||||
|
||||
<%+cbi/valuefooter%>
|
@ -1,7 +1,13 @@
|
||||
|
||||
config unblockneteasemusic 'config'
|
||||
option enable '0'
|
||||
option music_source 'default'
|
||||
option follow_source_order '0'
|
||||
option local_vip '0'
|
||||
option enable_flac '0'
|
||||
option disable_upgrade_check '1'
|
||||
option replace_music_source 'dont_replace'
|
||||
option use_custom_cookie '0'
|
||||
option auto_update '1'
|
||||
option update_time '3'
|
||||
|
||||
option advanced_mode '0'
|
||||
|
@ -50,8 +50,6 @@ append_param_boolenv() {
|
||||
append_filter_client() {
|
||||
local cfg="$1"
|
||||
|
||||
is_enabled "$cfg" "enable" || return 1
|
||||
|
||||
local ip_addr filter_mode
|
||||
config_get ip_addr "$cfg" "ip_addr"
|
||||
config_get filter_mode "$cfg" "filter_mode"
|
||||
@ -106,7 +104,7 @@ start_service() {
|
||||
config_get http_port "config" "http_port" "5200"
|
||||
config_get https_port "config" "https_port" "5201"
|
||||
config_get hijack_ways "config" "hijack_ways" "use_ipset"
|
||||
[ "$hijack_ways" != "use_hosts" ] || { http_port="80"; https_port="443"; }
|
||||
[ "${hijack_ways}" = "use_hosts" ] && { http_port="80"; https_port="443"; }
|
||||
append_param "-p" "${http_port}":"${https_port}"
|
||||
|
||||
if [ -n "$FW4" ]; then
|
||||
@ -130,7 +128,10 @@ start_service() {
|
||||
fi
|
||||
fi
|
||||
|
||||
append_param_arg "config" "music_source" "-o"
|
||||
local music_source
|
||||
config_get music_source "config" "music_source" "default"
|
||||
[ "${music_source}" != "default" ] && append_param -o "${music_source}"
|
||||
|
||||
append_param_arg "config" "cnrelay" "-c"
|
||||
append_param_arg "config" "endpoint_url" "-e" "https://music.163.com"
|
||||
append_param_arg "config" "netease_server_ip" "-f"
|
||||
@ -152,10 +153,8 @@ start_service() {
|
||||
append_param_boolenv "config" "follow_source_order" "FOLLOW_SOURCE_ORDER"
|
||||
append_param_boolenv "config" "search_album" "SEARCH_ALBUM"
|
||||
append_param_boolenv "config" "enable_flac" "ENABLE_FLAC"
|
||||
append_param_boolenv "config" "select_max_br" "SELECT_MAX_BR"
|
||||
append_param_boolenv "config" "disable_upgrade_check" "DISABLE_UPGRADE_CHECK"
|
||||
append_param_boolenv "config" "block_ads" "BLOCK_ADS"
|
||||
append_param_boolenv "config" "local_vip" "ENABLE_LOCAL_VIP"
|
||||
append_param_boolenv "config" "disable_upgrade_check" "DISABLE_UPGRADE_CHECK"
|
||||
case "$(config_get "config" "replace_music_source")" in
|
||||
"lower_than_192kbps") procd_append_param env MIN_BR="192000" ;;
|
||||
"lower_than_320kbps") procd_append_param env MIN_BR="320000" ;;
|
||||
|
25
luci-app-unblockneteasemusic/root/etc/uci-defaults/luci-unblockneteasemusic
Normal file → Executable file
@ -1,23 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$(uci -q get unblockneteasemusic.config.music_source)" = "default" ]; then
|
||||
uci -q delete "unblockneteasemusic.config.music_source"
|
||||
uci -q commit "unblockneteasemusic"
|
||||
fi
|
||||
|
||||
uci -q batch <<-EOF >"/dev/null"
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@unblockneteasemusic[-1]
|
||||
add ucitrack unblockneteasemusic
|
||||
set ucitrack.@unblockneteasemusic[-1].init=unblockneteasemusic
|
||||
commit ucitrack
|
||||
EOF
|
||||
[ -e "$(command -v fw4)" ] || {
|
||||
uci -q batch <<-EOF >"/dev/null"
|
||||
delete firewall.unblockneteasemusic
|
||||
set firewall.unblockneteasemusic=include
|
||||
set firewall.unblockneteasemusic.type=script
|
||||
set firewall.unblockneteasemusic.path=/var/etc/unblockneteasemusic.include
|
||||
set firewall.unblockneteasemusic.reload=1
|
||||
commit firewall
|
||||
EOF
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete firewall.unblockneteasemusic
|
||||
set firewall.unblockneteasemusic=include
|
||||
set firewall.unblockneteasemusic.type=script
|
||||
set firewall.unblockneteasemusic.path=/var/etc/unblockneteasemusic.include
|
||||
set firewall.unblockneteasemusic.reload=1
|
||||
commit firewall
|
||||
EOF
|
||||
}
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"admin/services/unblockneteasemusic": {
|
||||
"title": "解除网易云音乐播放限制",
|
||||
"order": 50,
|
||||
"action": {
|
||||
"type": "firstchild"
|
||||
},
|
||||
"depends": {
|
||||
"acl": [ "luci-app-unblockneteasemusic" ],
|
||||
"uci": { "unblockneteasemusic": true }
|
||||
}
|
||||
},
|
||||
"admin/services/unblockneteasemusic/config": {
|
||||
"title": "基本设定",
|
||||
"order": 10,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "unblockneteasemusic/config"
|
||||
}
|
||||
},
|
||||
"admin/services/unblockneteasemusic/status": {
|
||||
"title": "状态信息",
|
||||
"order": 20,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "unblockneteasemusic/status"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +1,10 @@
|
||||
{
|
||||
"luci-app-unblockneteasemusic": {
|
||||
"description": "Grant access to UnblockNeteaseMusic configuration",
|
||||
"description": "Grant UCI access for luci-app-unblockneteasemusic",
|
||||
"read": {
|
||||
"file": {
|
||||
"/etc/init.d/unblockneteasemusic": [ "exec" ],
|
||||
"/tmp/unblockneteasemusic.log": [ "read" ],
|
||||
"/usr/bin/unm-debug": [ "exec" ],
|
||||
"/usr/share/unblockneteasemusic/update.sh": [ "exec" ],
|
||||
"/usr/share/unblockneteasemusic/core/ca.crt": [ "read" ]
|
||||
},
|
||||
"ubus": {
|
||||
"service": [ "list" ]
|
||||
},
|
||||
"uci": [ "unblockneteasemusic" ]
|
||||
},
|
||||
"write": {
|
||||
"file": {
|
||||
"/usr/share/unblockneteasemusic/server.crt": [ "write" ],
|
||||
"/usr/share/unblockneteasemusic/server.key": [ "write" ]
|
||||
},
|
||||
"uci": [ "unblockneteasemusic" ]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
# Copyright (C) 2019-2023 Tianling Shen <cnsztl@immortalwrt.org>
|
||||
# Copyright (C) 2019-2022 Tianling Shen <cnsztl@immortalwrt.org>
|
||||
|
||||
NAME="unblockneteasemusic"
|
||||
LOCK="/tmp/$NAME.update_core.lock"
|
||||
@ -65,6 +65,7 @@ update_core() {
|
||||
}
|
||||
done
|
||||
|
||||
[ -z "${update_core_from_luci}" ] || touch "/usr/share/$NAME/update_core_successfully"
|
||||
echo -e "${core_latest_ver}" > "/usr/share/$NAME/core_local_ver"
|
||||
[ -n "${non_restart}" ] || /etc/init.d/"$NAME" restart
|
||||
|
||||
@ -74,17 +75,6 @@ update_core() {
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
"check_version")
|
||||
if [ ! -e "/usr/share/$NAME/core_local_ver" ] || [ ! -e "/usr/share/$NAME/core/app.js" ]; then
|
||||
echo -e "Not installed."
|
||||
exit 2
|
||||
else
|
||||
version="$(node "/usr/share/$NAME/core/app.js" -v)"
|
||||
commit="$(cat "/usr/share/$NAME/core_local_ver" | head -c7)"
|
||||
echo "$version ($commit)"
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
"update_core")
|
||||
check_core_if_already_running
|
||||
check_core_latest_version
|
||||
@ -94,11 +84,12 @@ case "$1" in
|
||||
check_core_if_already_running
|
||||
check_core_latest_version
|
||||
;;
|
||||
"remove_core")
|
||||
/etc/init.d/"$NAME" stop
|
||||
rm -rf "/usr/share/$NAME/core" "/usr/share/$NAME/core_local_ver" "$LOCK"
|
||||
"update_core_from_luci")
|
||||
update_core_from_luci=1
|
||||
check_core_if_already_running
|
||||
check_core_latest_version
|
||||
;;
|
||||
*)
|
||||
echo -e "Usage: $0/update.sh check_version | update_core | remove_core"
|
||||
echo -e "Usage: $0/update.sh update_core"
|
||||
;;
|
||||
esac
|
||||
|
Before Width: | Height: | Size: 776 KiB After Width: | Height: | Size: 786 KiB |
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 165 KiB |
BIN
luci-app-unblockneteasemusic/views/view4.jpg
Normal file
After Width: | Height: | Size: 117 KiB |