update 2023-01-02 20:15:39
@ -16,7 +16,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-amlogic
|
||||
PKG_VERSION:=3.1.153
|
||||
PKG_VERSION:=3.1.154
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0 License
|
||||
|
||||
@ -130,7 +130,7 @@ check_kernel() {
|
||||
# check if kernel is locked
|
||||
if [ -n "${LOCK_KERNEL}" ]; then
|
||||
if [ "${LOCK_KERNEL}" != "${kernel_name}" ]; then
|
||||
if ! echo "${kernel_name}" | grep -E '^5.10.\d+-.*?rk3588.*?$' >/dev/null; then
|
||||
if ! echo "${kernel_name}" | grep -E '^5.10.\d+-.*?rk35.*?$' >/dev/null; then
|
||||
error_msg "The kernel version is locked to [ ${LOCK_KERNEL} ], but your kernel is [ ${kernel_name} ]. "
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
# Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-lucky
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-lucky
|
||||
PKG_VERSION:=1.0.4
|
||||
PKG_RELEASE:=4
|
||||
|
||||
LUCI_TITLE:=LuCI Support for Dynamic lucky Client
|
||||
LUCI_DEPENDS:=+lucky
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
# Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-lucky
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-lucky
|
||||
PKG_VERSION:=1.0.4
|
||||
PKG_RELEASE:=5
|
||||
|
||||
LUCI_TITLE:=LuCI Support for Dynamic lucky Client
|
||||
LUCI_DEPENDS:=+lucky
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
||||
@ -1,179 +0,0 @@
|
||||
### 访问数:[] [](https://t.me/joinchat/AAAAAEpRF88NfOK5vBXGBQ)
|
||||
|
||||
欢迎来到sirpdboy的源码仓库!
|
||||
=
|
||||
# Lucky(大吉)
|
||||
|
||||
luci-app-lucky 动态域名ddns-go服务,替代socat主要用于公网IPv6 tcp/udp转内网ipv4,http/https反向代理
|
||||
|
||||
[](#解决-github-网页上图片显示失败的问题) [](https://t.me/joinchat/AAAAAEpRF88NfOK5vBXGBQ)
|
||||
|
||||
[luci-app-lucky Lucky(大吉)](https://github.com/sirpdboy/luci-app-lucky)
|
||||
======================
|
||||
|
||||
|
||||
请 **认真阅读完毕** 本页面,本页面包含注意事项和如何使用。
|
||||
|
||||
## 功能说明:
|
||||
|
||||
### Lucky(大吉)
|
||||
|
||||
#### 动态域名ddns-go服务,替代socat主要用于公网IPv6 tcp/udp转内网ipv4,http/https反向代理
|
||||
|
||||
#### 在LUCI中可以配置访问端口和增加是否允许外网访问设置。
|
||||
|
||||
<!-- TOC -->
|
||||
|
||||
- [lucky](#lucky)
|
||||
- [特性](#特性)
|
||||
- [使用方法](#使用方法)
|
||||
- [说明](#说明)
|
||||
- [问题](#常见问题)
|
||||
- [界面](#界面)
|
||||
- [捐助](#捐助)
|
||||
|
||||
|
||||
<!-- /TOC -->
|
||||
|
||||
## 特性
|
||||
|
||||
- 目前已经实现的功能有
|
||||
- 1.替代socat,主要用于公网IPv6 tcp/udp转 内网ipv4
|
||||
- 支持界面化(web后台)管理转发规则,单条转发规则支持设置多个转发端口,一键开关指定转发规则
|
||||
- 单条规则支持黑白名单安全模式切换,白名单模式可以让没有安全验证的内网服务端口稍微安全一丢丢暴露到公网
|
||||
- Web后台支持查看最新100条日志
|
||||
- 另有精简版不带后台,支持命令行快捷设置转发规则,有利于空间有限的嵌入式设备运行.(不再提供编译版本,如有需求可以自己编译)
|
||||
- 2.动态域名服务
|
||||
- 参考和部分代码来自 https://github.com/jeessy2/ddns-go
|
||||
- 在ddns-go的基础上主要改进/增加的功能有
|
||||
- 1.同时支持接入多个不同的DNS服务商
|
||||
- 2.支持http/https/socks5代理设置
|
||||
- 3.自定义(Callback)和Webhook支持自定义headers
|
||||
- 4.支持BasicAuth
|
||||
- 5.DDNS任务列表即可了解全部信息(包含错误信息),无需单独查看日志.
|
||||
- 6.调用DNS服务商接口更新域名信息前可以先通过DNS解析域名比较IP,减少对服务商接口调用.
|
||||
- 其它细节功能自己慢慢发现...
|
||||
- 没有文档,后台各处的提示信息已经足够多.
|
||||
- 支持的DNS服务商和DDNS-GO一样,有Alidns(阿里云),百度云,Cloudflare,Dnspod(腾讯云),华为云.自定义(Callback)内置有每步,No-IP,Dynv6,Dynu模版,一键填充,仅需修改相应用户密码或者token即可快速接入.
|
||||
- 3.http/https反向代理
|
||||
- 特点
|
||||
- 设置简单
|
||||
- 支持HttpBasic认证
|
||||
- 支持IP黑白名单
|
||||
- 支持UserAgent黑白名单
|
||||
- 日志记录最近访问情况
|
||||
- 一键开关子规则
|
||||
- 前端域名与后端地址 支持一对一,一对多(均衡负载),多对多(下一级反向代理)
|
||||
- 4.网络唤醒
|
||||
- 特点
|
||||
- 支持远程控制唤醒和关机操作
|
||||
- 远程唤醒需要 待唤醒端所在局域网内有开启中继唤醒指令的lucky唤醒客户端
|
||||
- 远程关机需要 待关机端运行有luck唤醒客户端
|
||||
- 支持接入第三方物联网平台(点灯科技 巴法云),可通过各大平台的语音助手控制设备唤醒和关机.
|
||||
- 点灯科技支持 小爱同学 小度 天猫精灵
|
||||
- 巴法云支持小爱同学 小度 天猫精灵 google语音 AmazonAlexa
|
||||
- 具备但一般用不上的功能:支持一个设备设置多组网卡mac和多个广播地址,实现批量控制设备.
|
||||
|
||||
## 使用方法
|
||||
|
||||
- 将luci-app-lucky添加至 LEDE/OpenWRT 源码的方法。
|
||||
|
||||
### 下载源码方法一:
|
||||
- 编辑源码文件夹根目录feeds.conf.default并加入如下内容:
|
||||
|
||||
```Brach
|
||||
|
||||
# feeds获取源码:
|
||||
|
||||
src-git luci-app-lucky https://github.com/sirpdboy/luci-app-lucky
|
||||
```
|
||||
```Brach
|
||||
|
||||
# 更新feeds,并安装主题:
|
||||
|
||||
scripts/feeds update luci-app-lucky
|
||||
scripts/feeds install luci-app-lucky
|
||||
```
|
||||
|
||||
### 下载源码方法二:
|
||||
|
||||
```Brach
|
||||
|
||||
# 下载源码
|
||||
|
||||
git clone https://github.com/sirpdboy/luci-app-lucky.git package/lucky
|
||||
make menuconfig
|
||||
|
||||
```
|
||||
### 配置菜单
|
||||
|
||||
```Brach
|
||||
make menuconfig
|
||||
# 找到 LuCI -> Applications, 选择 luci-app-lucky, 保存后退出。
|
||||
```
|
||||
|
||||
### 编译
|
||||
|
||||
```Brach
|
||||
# 编译固件
|
||||
make package/lucky/luci-app-lucky/compile V=s
|
||||
```
|
||||
|
||||
## 说明
|
||||
|
||||
- 源码来源:https://github.com/gdy666/lucky
|
||||
- 源码来源:https://github.com/sirpdboy/luci-app-lucky
|
||||
- 你可以随意使用其中的源码,但请注明出处。
|
||||
|
||||
## 常见问题
|
||||
|
||||
- 不同于防火墙端口转发规则,不要设置没有用上的端口,会增加内存的使用.
|
||||
- 小米路由 ipv4 类型的80和443端口被占用,但只设置监听tcp6(ipv6)的80/443端口转发规则完全没问题.
|
||||
- 如果需要使用白名单模式,请根据自身需求打开外网访问后台管理页面开关.
|
||||
- 转发规则启用异常,端口转发没有生效时请登录后台查看日志.
|
||||
- 开启外网访问可以直接修改配置文件中的"AllowInternetaccess": false, 将false改为true
|
||||
|
||||
|
||||
## 界面
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
# My other project
|
||||
|
||||
网络速度测试 :https://github.com/sirpdboy/NetSpeedTest
|
||||
|
||||
定时设置插件 : https://github.com/sirpdboy/luci-app-autotimeset
|
||||
|
||||
关机功能插件 : https://github.com/sirpdboy/luci-app-poweroffdevice
|
||||
|
||||
opentopd主题 : https://github.com/sirpdboy/luci-theme-opentopd
|
||||
|
||||
opentoks 主题: https://github.com/sirpdboy/luci-theme-opentoks [仿KOOLSAHRE主题]
|
||||
|
||||
btmob 主题: https://github.com/sirpdboy/luci-theme-btmob
|
||||
|
||||
系统高级设置 : https://github.com/sirpdboy/luci-app-advanced
|
||||
|
||||
DDNS-GO动态域名: https://github.com/sirpdboy/luci-app-DDNS-GO
|
||||
|
||||
Lucky(大吉): https://github.com/sirpdboy/luci-app-lucky
|
||||
|
||||
|
||||
## 捐助
|
||||
|
||||
-如果你觉得此项目对你有帮助,请捐助我们,以使项目能持续发展,更加完善。··请作者喝杯咖啡~~~**
|
||||
-你们的支持就是我的动力!**
|
||||
|
||||
| <img src="https://img.shields.io/badge/-支付宝-F5F5F5.svg" href="#赞助支持本项目-" height="25" alt="图飞了😂"/> | <img src="https://img.shields.io/badge/-微信-F5F5F5.svg" height="25" alt="图飞了😂" href="#赞助支持本项目-"/> |
|
||||
| :-----------------: | :-------------: |
|
||||
| |  |
|
||||
|
||||
<a href="#readme">
|
||||
<img src="https://img.shields.io/badge/-返回顶部-orange.svg" alt="图飞了😂" title="返回顶部" align="right"/>
|
||||
</a>
|
||||
|
||||
@ -4,9 +4,6 @@
|
||||
module("luci.controller.lucky", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/lucky") then
|
||||
return
|
||||
end
|
||||
|
||||
entry({"admin", "services", "lucky"}, alias("admin", "services", "lucky", "setting"),_("Lucky"), 57).dependent = true
|
||||
entry({"admin", "services", "lucky", "setting"}, cbi("lucky"), _("Base Setting"), 20).leaf=true
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<%#
|
||||
Copyright 2021-2022 sirpdboy Wich <sirpdboy@qq.com>
|
||||
Copyright 2021-2022 sirpdboy Wich <herboy2008@gmail.com>
|
||||
https://github.com/sirpdboy/luci-app-lucky
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local safeURL = luci.sys.exec("cat /etc/lucky/lucky.conf | grep SafeURL | sed 's/\"//g' | sed 's/: /\\n/g'|sed '1d' ");
|
||||
local safeURL = luci.sys.exec("cat /etc/lucky/lucky.conf | grep SafeURL | sed -e 's/,//g' -e 's/\"//g' -e 's/\ //g' | awk -F ':' '{print $2}' ")
|
||||
local luckyHttpPort = luci.model.uci.cursor():get("lucky", "lucky", "port");
|
||||
-%>
|
||||
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
<%#
|
||||
Copyright 2021-2022 sirpdboy Wich <herboy2008@gmail.com>
|
||||
https://github.com/sirpdboy/luci-app-lucky
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
|
||||
@ -1,56 +1,56 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "Lucky"
|
||||
msgstr "Lucky大吉"
|
||||
|
||||
msgid "Main functions of Lucky: dynamic domain name ddns-go service, which replaces socat. It is mainly used for public IPv6 tcp/udp to intranet ipv4, http/https reverse proxy frp"
|
||||
msgstr "大吉主要功能:动态域名ddns-go服务,替代socat主要用于公网IPv6 tcp/udp转内网ipv4,http/https反向代理,网络唤醒(可通过第三方物联网平台接入各大语音助手实现语音控制开关电脑)"
|
||||
|
||||
msgid "Running state"
|
||||
msgstr "运行状态"
|
||||
|
||||
msgid "The Lucky service is running."
|
||||
msgstr "大吉服务已启动"
|
||||
|
||||
msgid "The Lucky service is not running."
|
||||
msgstr "大吉服务未启动"
|
||||
|
||||
msgid "Lucky Status"
|
||||
msgstr "大吉服务状态"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "收集数据..."
|
||||
|
||||
msgid "Set the Lucky access port"
|
||||
msgstr "设置访问端口"
|
||||
|
||||
msgid "Lucky configuration file"
|
||||
msgstr "Lucky 配置文件"
|
||||
|
||||
msgid "</br>For specific usage, see:"
|
||||
msgstr "</br>具体使用方法参见:"
|
||||
|
||||
msgid "Base Setting"
|
||||
msgstr "基本设置"
|
||||
|
||||
msgid "Enable Internet access"
|
||||
msgstr "开启外网访问"
|
||||
|
||||
msgid "Click the new page to open Lucky"
|
||||
msgstr "点击新页面打开大吉"
|
||||
|
||||
msgid "View Password"
|
||||
msgstr "查看密码"
|
||||
|
||||
msgid "Username:"
|
||||
msgstr "用户名:"
|
||||
|
||||
msgid "Password:"
|
||||
msgstr "密码:"
|
||||
|
||||
msgid "Reading..."
|
||||
msgstr "读取中..."
|
||||
|
||||
msgid "Read"
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8"
|
||||
|
||||
msgid "Lucky"
|
||||
msgstr "Lucky大吉"
|
||||
|
||||
msgid "Main functions of Lucky: dynamic domain name ddns-go service, which replaces socat. It is mainly used for public IPv6 tcp/udp to intranet ipv4, http/https reverse proxy frp"
|
||||
msgstr "大吉主要功能:动态域名ddns-go服务,替代socat主要用于公网IPv6 tcp/udp转内网ipv4,http/https反向代理,网络唤醒(可通过第三方物联网平台接入各大语音助手实现语音控制开关电脑)"
|
||||
|
||||
msgid "Running state"
|
||||
msgstr "运行状态"
|
||||
|
||||
msgid "The Lucky service is running."
|
||||
msgstr "大吉服务已启动"
|
||||
|
||||
msgid "The Lucky service is not running."
|
||||
msgstr "大吉服务未启动"
|
||||
|
||||
msgid "Lucky Status"
|
||||
msgstr "大吉服务状态"
|
||||
|
||||
msgid "Collecting data..."
|
||||
msgstr "收集数据..."
|
||||
|
||||
msgid "Set the Lucky access port"
|
||||
msgstr "设置访问端口"
|
||||
|
||||
msgid "Lucky configuration file"
|
||||
msgstr "Lucky 配置文件"
|
||||
|
||||
msgid "</br>For specific usage, see:"
|
||||
msgstr "</br>具体使用方法参见:"
|
||||
|
||||
msgid "Base Setting"
|
||||
msgstr "基本设置"
|
||||
|
||||
msgid "Enable Internet access"
|
||||
msgstr "开启外网访问"
|
||||
|
||||
msgid "Click the new page to open Lucky"
|
||||
msgstr "点击新页面打开大吉"
|
||||
|
||||
msgid "View Password"
|
||||
msgstr "查看密码"
|
||||
|
||||
msgid "Username:"
|
||||
msgstr "用户名:"
|
||||
|
||||
msgid "Password:"
|
||||
msgstr "密码:"
|
||||
|
||||
msgid "Reading..."
|
||||
msgstr "读取中..."
|
||||
|
||||
msgid "Read"
|
||||
msgstr "读取"
|
||||
@ -1,5 +1,5 @@
|
||||
config lucky 'lucky'
|
||||
option enabled '0'
|
||||
option logger '1'
|
||||
option port '16601'
|
||||
option AllowInternetaccess '0'
|
||||
config lucky 'lucky'
|
||||
option enabled '0'
|
||||
option logger '1'
|
||||
option port '16601'
|
||||
option AllowInternetaccess '0'
|
||||
|
||||
58
luci-app-lucky/luci-app-lucky/root/etc/init.d/lucky
Normal file
@ -0,0 +1,58 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-lucky
|
||||
|
||||
# This file is part of lucky .
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
|
||||
|
||||
USE_PROCD=1
|
||||
START=99
|
||||
STOP=10
|
||||
|
||||
CONF="lucky"
|
||||
PROG=/usr/bin/lucky
|
||||
LUCKYDIR=/etc/lucky
|
||||
LUCKYCONF=/etc/lucky/lucky.conf
|
||||
|
||||
get_config() {
|
||||
config_get_bool enabled $1 enabled 1
|
||||
config_get_bool logger $1 logger 1
|
||||
config_get port $1 port 16601
|
||||
config_get AllowInternetaccess $1 AllowInternetaccess 0
|
||||
}
|
||||
|
||||
lucky_prepare() {
|
||||
pgrep -f $PROG | xargs kill -9 >/dev/null 2>&1
|
||||
}
|
||||
|
||||
|
||||
start_service() {
|
||||
stop_service
|
||||
config_load "$CONF"
|
||||
config_foreach get_config "$CONF"
|
||||
|
||||
[ "x$enabled" = "x1" ] || return 1
|
||||
if [ "x$AllowInternetaccess" = "x1" ] ;then
|
||||
sed -i 's/"AllowInternetaccess": false,/"AllowInternetaccess": true,/g' "$LUCKYCONF"
|
||||
else
|
||||
sed -i 's/"AllowInternetaccess": true,/"AllowInternetaccess": false,/g' "$LUCKYCONF"
|
||||
fi
|
||||
# set_firewall
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_append_param command -c "$LUCKYCONF" -p $port
|
||||
[ "x$logger" == x1 ] && procd_set_param stderr 1
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
lucky_prepare
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$CONF"
|
||||
}
|
||||
@ -1,11 +1,11 @@
|
||||
{
|
||||
"luci-app-lucky": {
|
||||
"description": "Grant UCI access for luci-app-lucky",
|
||||
"read": {
|
||||
"uci": [ "lucky" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "lucky" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"luci-app-lucky": {
|
||||
"description": "Grant UCI access for luci-app-lucky",
|
||||
"read": {
|
||||
"uci": [ "lucky" ]
|
||||
},
|
||||
"write": {
|
||||
"uci": [ "lucky" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,90 +1,70 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
# Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=lucky
|
||||
PKG_VERSION:=1.7.5
|
||||
PKG_RELEASE:=1
|
||||
PKGARCH:=all
|
||||
|
||||
ifeq ($(ARCH),mipsel)
|
||||
LUCKY_ARCH:=mipsle_softfloat
|
||||
endif
|
||||
ifeq ($(ARCH),mips)
|
||||
LUCKY_ARCH:=mips_softfloat
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
LUCKY_ARCH:=i386
|
||||
endif
|
||||
ifeq ($(ARCH),x86_64)
|
||||
LUCKY_ARCH:=x86_64
|
||||
endif
|
||||
ifeq ($(ARCH),arm)
|
||||
LUCKY_ARCH:=armv7
|
||||
endif
|
||||
ifeq ($(BOARD),bcm53xx)
|
||||
LUCKY_ARCH:=armv6
|
||||
ifeq ($(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE)))),)
|
||||
LUCKY_ARCH:=armv5
|
||||
endif
|
||||
endif
|
||||
ifeq ($(BOARD),kirkwood)
|
||||
LUCKY_ARCH:=armv5
|
||||
endif
|
||||
ifeq ($(ARCH),aarch64)
|
||||
LUCKY_ARCH:=arm64
|
||||
endif
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-only
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=GDY666 <gdy666@foxmail.com>
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_HASH:=skip
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Lucky gdy
|
||||
DEPENDS:=@(i386||x86_64||arm||aarch64||mipsel||mips)
|
||||
URL:=https://github.com/gdy666/lucky
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
Main functions of Lucky: ipv4/ipv6 portforward,ddns,IOT wake on lan ,reverse proxy and more...
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
#!/bin/sh
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
[ -f /etc/uci-defaults/luci-lucky ] && /etc/uci-defaults/luci-lucky && rm -f /etc/uci-defaults/luci-lucky
|
||||
fi
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
[ ! -f $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz ] && wget https://github.com/gdy666/lucky/releases/download/v$(PKG_VERSION)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -O $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz
|
||||
tar -xzvf $(PKG_BUILD_DIR)/$(PKG_NAME)_$(PKG_VERSION)_Linux_$(LUCKY_ARCH).tar.gz -C $(PKG_BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d $(1)/etc/uci-defaults $(1)/etc/lucky/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lucky $(1)/usr/bin/lucky
|
||||
$(INSTALL_BIN) ./files/lucky.init $(1)/etc/init.d/lucky
|
||||
$(INSTALL_BIN) ./files/luci-lucky.uci-default $(1)/etc/uci-defaults/luci-lucky
|
||||
$(INSTALL_DATA) ./files/default.conf $(1)/etc/lucky/lucky.conf
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
#
|
||||
# Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=lucky
|
||||
PKG_VERSION:=1.7.5
|
||||
PKG_RELEASE:=1
|
||||
PKGARCH:=all
|
||||
|
||||
ifeq ($(ARCH),mipsel)
|
||||
LUCKY_ARCH:=mipsle_softfloat
|
||||
endif
|
||||
ifeq ($(ARCH),mips)
|
||||
LUCKY_ARCH:=mips_softfloat
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
LUCKY_ARCH:=i386
|
||||
endif
|
||||
ifeq ($(ARCH),x86_64)
|
||||
LUCKY_ARCH:=x86_64
|
||||
endif
|
||||
ifeq ($(ARCH),arm)
|
||||
LUCKY_ARCH:=armv7
|
||||
endif
|
||||
ifeq ($(BOARD),bcm53xx)
|
||||
LUCKY_ARCH:=armv6
|
||||
ifeq ($(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE)))),)
|
||||
LUCKY_ARCH:=armv5
|
||||
endif
|
||||
endif
|
||||
ifeq ($(BOARD),kirkwood)
|
||||
LUCKY_ARCH:=armv5
|
||||
endif
|
||||
ifeq ($(ARCH),aarch64)
|
||||
LUCKY_ARCH:=arm64
|
||||
endif
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-only
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=GDY666 <gdy666@foxmail.com>
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_HASH:=skip
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=Lucky gdy
|
||||
DEPENDS:=@(i386||x86_64||arm||aarch64||mipsel||mips)
|
||||
URL:=https://github.com/gdy666/lucky
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/description
|
||||
Main functions of Lucky: ipv4/ipv6 portforward,ddns,IOT wake on lan ,reverse proxy and more...
|
||||
endef
|
||||
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lucky $(1)/usr/bin/lucky
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2021-2022 sirpdboy <herboy2008@gmail.com> https://github.com/sirpdboy/luci-app-lucky
|
||||
#
|
||||
# This file is part of lucky .
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
START=99
|
||||
STOP=15
|
||||
|
||||
|
||||
USE_PROCD=1
|
||||
|
||||
CONF=lucky
|
||||
PROG=/usr/bin/lucky
|
||||
LUCKYDIR=/etc/lucky
|
||||
LUCKYCONF=$LUCKYDIR/lucky.conf
|
||||
|
||||
get_config() {
|
||||
config_get_bool enabled $1 enabled 1
|
||||
config_get_bool logger $1 logger 1
|
||||
config_get port $1 port 16601
|
||||
config_get AllowInternetaccess $1 AllowInternetaccess 0
|
||||
}
|
||||
|
||||
set_firewall() {
|
||||
if [ "x$AllowInternetaccess" = "x1" ]; then
|
||||
uci -q delete firewall.lucky
|
||||
uci set firewall.lucky=rule
|
||||
uci set firewall.lucky.name="lucky"
|
||||
uci set firewall.lucky.target="ACCEPT"
|
||||
uci set firewall.lucky.src="wan"
|
||||
uci set firewall.lucky.proto='tcp udp'
|
||||
uci set firewall.lucky.dest_port="$port"
|
||||
uci set firewall.lucky.enabled="1"
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall reload >/dev/null 2>&1
|
||||
else
|
||||
uci -q delete firewall.lucky
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall reload >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
start_service() {
|
||||
stop_service
|
||||
config_load "$CONF"
|
||||
config_foreach get_config "$CONF"
|
||||
|
||||
[ -s ${LUCKYCONF} ] || {
|
||||
[ -d "$LUCKYDIR" ] || mkdir -p "$LUCKYDIR" >/dev/null 2>&1
|
||||
cat > $LUCKYCONF <<EOF
|
||||
{"BaseConfigure": {"AdminWebListenPort": $port,"AdminWebListenTLS": false,"AdminWebListenHttpsPort": 16626,"AdminAccount": "666","AdminPassword": "666","AllowInternetaccess": false,"LogMaxSize": 2048,"HttpClientTimeout": 20,"InsecureSkipVerify": false,"DisableModules": null,"SafeURL": ""},"WhiteListConfigure": {"BaseConfigure": {"URL": "","ActivelifeDuration": 36,"BasicAccount": "666","BasicPassword": "666"},"WhiteList": null},"BlackListConfigure": {"BlackList": null},"DDNSConfigure": {"Enable": false,"FirstCheckDelay": 0,"Intervals": 0},"DDNSTaskList": null,"ReverseProxyRuleList": null,"SSLCertficateList": null,"PortForwardsRuleList": null,"PortForwardsConfigure": {"PortForwardsLimit": 128,"TCPPortforwardMaxConnections": 1024,"UDPReadTargetDataMaxgoroutineCount": 1024},"WOLDeviceList": null,"WOLServiceConfigure": {"Server": {"Enable": false,"Token": "666666" },"Client": {"Enable": false,"ServerURL": "","Token": "","Relay": false,"Key": "","DeviceName": "OpenWrt","Mac": "","BroadcastIP": "","Port": 9,"Repeat": 5,"PowerOffCMD": "poweroff","UpdateTime": 0}}}
|
||||
EOF
|
||||
}
|
||||
|
||||
[ "x$enabled" = "x1" ] || return 1
|
||||
if [ "x$AllowInternetaccess" = "x1" ] ;then
|
||||
sed -i 's/"AllowInternetaccess": false,/"AllowInternetaccess": true,/g' "$LUCKYCONF"
|
||||
else
|
||||
sed -i 's/"AllowInternetaccess": true,/"AllowInternetaccess": false,/g' "$LUCKYCONF"
|
||||
fi
|
||||
set_firewall
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG"
|
||||
procd_append_param command -c "$LUCKYCONF" -p $port
|
||||
[ "x$logger" == x1 ] && procd_set_param stderr 1
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
killall -9 "$PROG" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$CONF"
|
||||
}
|
||||
@ -4,14 +4,15 @@
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for UnblockNeteaseMusic
|
||||
LUCI_DEPENDS:=+dnsmasq-full +ipset +node \
|
||||
LUCI_TITLE:=LuCI support for UnblockNeteaseMusic (JavaScript)
|
||||
LUCI_DEPENDS:=+dnsmasq-full +node \
|
||||
+PACKAGE_firewall:ipset \
|
||||
@(PACKAGE_libustream-mbedtls||PACKAGE_libustream-openssl||PACKAGE_libustream-wolfssl)
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
PKG_NAME:=luci-app-unblockneteasemusic
|
||||
PKG_VERSION:=2.13
|
||||
PKG_RELEASE:=5
|
||||
PKG_VERSION:=3.1
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||
|
||||
|
||||
@ -42,11 +42,10 @@
|
||||
|
||||
### 效果图
|
||||
#### LuCI 界面
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
#### UWP 网易云音乐客户端
|
||||

|
||||

|
||||
|
||||
### 鸣谢
|
||||
[UnblockNeteaseMusic](https://github.com/UnblockNeteaseMusic/server)的开发者:[nondanee](https://github.com/nondanee)、[pan93412](https://github.com/pan93412)、[1715173329](https://github.com/1715173329)<br/>
|
||||
|
||||
@ -0,0 +1,336 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-only
|
||||
*
|
||||
* Copyright (C) 2022 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.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.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.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'search_album', _('附加专辑名'),
|
||||
_('在其他音源搜索歌曲时携带专辑名称(默认搜索条件 <code>歌曲名 - 歌手</code>,启用后搜索条件 <code>歌曲名 - 歌手 专辑名</code>)。')
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'local_vip', _('启用本地 VIP'),
|
||||
_('启用后,可以使用去广告、个性换肤、鲸云音效等本地功能。'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'enable_flac', _('启用无损音质'),
|
||||
_('目前仅支持酷狗、酷我、咪咕、pyncmd、QQ 音源。'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'disable_upgrade_check', _('禁用更新检查'),
|
||||
_('禁止客户端检查更新,全平台支持。'));
|
||||
o.default = o.enabled;
|
||||
o.rmempty = false;
|
||||
|
||||
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.rmempty = false;
|
||||
|
||||
o = s.option(form.Flag, 'auto_update', _('启用自动更新'),
|
||||
_('启用后,每天将定时自动检查最新版本并更新。'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
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.rmempty = false;
|
||||
|
||||
o = s.option(form.ListValue, 'log_level', _('日志等级'));
|
||||
o.value('debug', _('调试'));
|
||||
o.value('info', _('信息(默认)'));
|
||||
o.value('silent', _('静默'));
|
||||
o.default = 'info';
|
||||
o.rmempty = false;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Value, 'http_port', _('HTTP 监听端口'));
|
||||
o.datatype = 'port';
|
||||
o.default = '5200';
|
||||
o.rmempty = false;
|
||||
o.depends({'advanced_mode': '1', 'hijack_ways': 'dont_hijack'});
|
||||
o.depends({'advanced_mode': '1', 'hijack_ways': 'use_ipset'});
|
||||
|
||||
o = s.option(form.Value, 'https_port', _('HTTPS 监听端口'));
|
||||
o.datatype = 'port';
|
||||
o.default = '5201';
|
||||
o.rmempty = false;
|
||||
o.depends({'advanced_mode': '1', 'hijack_ways': 'dont_hijack'});
|
||||
o.depends({'advanced_mode': '1', '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 劫持,程序监听的 HTTP/HTTPS 端口将被锁定为 80/443。'));
|
||||
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.rmempty = false;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Flag, 'pub_access', _('部署到公网'),
|
||||
_('默认仅放行局域网请求,如需提供公开访问请勾选此选项。'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
o.depends('advanced_mode', '1');
|
||||
|
||||
o = s.option(form.Flag, 'strict_mode', _('启用严格模式'),
|
||||
_('若将服务部署到公网,则强烈建议使用严格模式,此模式下仅放行网易云音乐所属域名的请求。<br/>注意:该模式下不能使用全局代理。'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
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();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,224 @@
|
||||
/* 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
|
||||
});
|
||||
@ -1,69 +0,0 @@
|
||||
-- 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
|
||||
@ -1,14 +0,0 @@
|
||||
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
|
||||
@ -1,247 +0,0 @@
|
||||
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
|
||||
@ -1,19 +0,0 @@
|
||||
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
|
||||
@ -1,32 +0,0 @@
|
||||
<%+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%>
|
||||
@ -1,21 +0,0 @@
|
||||
<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>
|
||||
@ -1,36 +0,0 @@
|
||||
<%+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,13 +1,12 @@
|
||||
|
||||
config unblockneteasemusic 'config'
|
||||
option enable '0'
|
||||
option music_source 'default'
|
||||
option music_source ''
|
||||
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'
|
||||
|
||||
@ -46,6 +46,8 @@ append_param_env() {
|
||||
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"
|
||||
@ -124,10 +126,7 @@ start_service() {
|
||||
fi
|
||||
fi
|
||||
|
||||
local music_source
|
||||
config_get music_source "config" "music_source" "default"
|
||||
[ "${music_source}" != "default" ] && append_param -o "${music_source}"
|
||||
|
||||
append_param_arg "config" "music_source" "-o"
|
||||
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"
|
||||
|
||||
25
luci-app-unblockneteasemusic/root/etc/uci-defaults/luci-unblockneteasemusic
Executable file → Normal file
@ -1,20 +1,23 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
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"
|
||||
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
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
{
|
||||
"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,10 +1,24 @@
|
||||
{
|
||||
"luci-app-unblockneteasemusic": {
|
||||
"description": "Grant UCI access for luci-app-unblockneteasemusic",
|
||||
"description": "Grant access to UnblockNeteaseMusic configuration",
|
||||
"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" ]
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,6 @@ 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
|
||||
|
||||
@ -75,6 +74,17 @@ 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
|
||||
@ -84,12 +94,11 @@ case "$1" in
|
||||
check_core_if_already_running
|
||||
check_core_latest_version
|
||||
;;
|
||||
"update_core_from_luci")
|
||||
update_core_from_luci=1
|
||||
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"
|
||||
;;
|
||||
*)
|
||||
echo -e "Usage: $0/update.sh update_core"
|
||||
echo -e "Usage: $0/update.sh check_version | update_core | remove_core"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
Before Width: | Height: | Size: 786 KiB After Width: | Height: | Size: 776 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 185 KiB |
|
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 117 KiB |