update 2022-09-05 17:12:47

This commit is contained in:
github-actions[bot] 2022-09-05 17:12:47 +08:00
parent 6d63157ef8
commit 53dea0465c
214 changed files with 48608 additions and 138 deletions

86
alist/Makefile Normal file
View File

@ -0,0 +1,86 @@
#
# Copyright (C) 2015-2016 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=alist
PKG_VERSION:=2.6.4
PKG_WEB_VERSION:=2.6.4
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/alist-org/alist/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=3860f5cec5d809159c55498874c472386cd6142a932a5e7bbfb3b0f569e3e12b
PKG_LICENSE:=GPL-3.0
PKG_LICENSE_FILE:=LICENSE
PKG_MAINTAINER:=sbwml <admin@cooluc.com>
define Download/$(PKG_NAME)-web
FILE:=$(PKG_NAME)-web-$(PKG_WEB_VERSION).tar.gz
URL_FILE:=dist.tar.gz
URL:=https://github.com/alist-org/web-v2/releases/download/$(PKG_WEB_VERSION)/
HASH:=4189ce3c523e6b8f6bba55faefabc926f6ef793c8755c5c2a2d3f75532fb2243
endef
PKG_CONFIG_DEPENDS:=CONFIG_ALIST_COMPRESS_UPX
PKG_BUILD_DEPENDS:=golang/host
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
GO_PKG:=github.com/Xhofe/alist
ALIST_PKG:=github.com/Xhofe/alist/conf
GO_PKG_LDFLAGS:=-w -s
GO_PKG_LDFLAGS_X:=$(ALIST_PKG).GitTag=v$(PKG_VERSION)-$(ARCH)
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
define Package/$(PKG_NAME)/Default
SECTION:=net
CATEGORY:=Network
SUBMENU:=Web Servers/Proxies
TITLE:=Alist - Main program
URL:=https://alist-doc.nn.ci/
endef
define Package/$(PKG_NAME)/description
A file list program that supports multiple storage
endef
define Package/$(PKG_NAME)
$(call Package/alist/Default)
DEPENDS:=$(GO_ARCH_DEPENDS)
endef
define Package/$(PKG_NAME)/config
config ALIST_COMPRESS_UPX
bool "Compress executable files with UPX"
default n
endef
define Build/Prepare
$(call Build/Prepare/Default)
$(eval $(call Download,$(PKG_NAME)-web))
$(TAR) --strip-components=1 -C $(PKG_BUILD_DIR)/public -xzf $(DL_DIR)/$(PKG_NAME)-web-$(PKG_WEB_VERSION).tar.gz
$(CP) ./files/assets/. $(PKG_BUILD_DIR)/public/assets/
endef
define Build/Compile
$(call GoPackage/Build/Compile)
ifneq ($(CONFIG_ALIST_COMPRESS_UPX),)
$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/alist
endif
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/alist $(1)/usr/bin
endef
$(eval $(call GoBinPackage,$(PKG_NAME)))
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="640pt" height="640pt" viewBox="0 0 640 640" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g id="#75c4beff">
<path fill="#75c4be" opacity="1.00" d=" M 326.33 53.46 C 332.73 52.13 339.80 52.94 345.24 56.78 C 351.10 60.95 355.42 66.87 359.18 72.91 C 413.13 162.45 466.15 252.54 519.63 342.37 C 533.77 366.22 548.04 389.99 561.98 413.97 C 565.57 420.47 569.65 426.80 572.11 433.85 C 574.71 442.80 575.26 452.42 573.40 461.58 C 571.16 471.91 563.67 480.51 554.58 485.59 C 547.15 489.94 538.61 492.34 529.99 492.34 C 471.66 492.39 413.33 492.32 355.00 492.38 C 347.28 492.31 339.07 491.06 332.84 486.14 C 328.67 482.79 324.78 478.42 323.87 472.98 C 322.65 465.12 324.45 457.05 328.13 450.06 C 332.44 441.85 337.43 434.01 341.95 425.92 C 350.12 411.30 359.31 397.29 367.87 382.90 C 373.02 374.40 381.07 366.99 391.06 365.01 C 405.38 363.19 421.45 374.82 420.76 390.02 C 420.53 403.34 411.28 413.77 406.46 425.58 C 405.37 428.57 403.57 432.32 405.76 435.24 C 409.97 437.89 415.19 437.95 420.00 438.17 C 444.00 438.20 467.99 438.13 491.99 438.21 C 496.40 438.12 501.06 438.21 505.15 436.27 C 506.87 435.57 507.96 433.81 507.89 431.96 C 507.85 428.01 505.68 424.52 503.79 421.19 C 495.41 407.20 487.36 393.02 479.03 379.00 C 435.55 304.25 391.71 229.71 347.81 155.20 C 344.09 149.60 341.53 143.14 336.78 138.28 C 334.65 135.85 330.80 136.63 329.07 139.11 C 324.76 144.59 321.32 150.70 317.65 156.62 C 258.22 256.83 198.68 356.97 139.09 457.08 C 134.67 465.40 129.90 473.61 124.01 480.99 C 118.33 487.59 110.05 492.53 101.18 492.56 C 92.76 491.73 84.50 487.48 79.39 480.65 C 75.14 474.46 74.64 466.37 76.43 459.25 C 78.16 451.11 82.97 444.19 87.22 437.20 C 128.26 367.34 169.88 297.83 211.19 228.13 C 234.01 189.69 256.88 151.28 279.84 112.92 C 287.23 99.22 295.72 86.17 303.81 72.89 C 309.02 64.44 316.29 55.89 326.33 53.46 Z" />
</g>
<g id="#2c9fd6ff">
<path fill="#2c9fd6" opacity="1.00" d=" M 329.35 261.14 C 337.95 260.38 347.26 263.39 353.07 269.98 C 357.77 275.75 360.69 283.43 358.96 290.91 C 357.79 299.89 351.32 306.64 347.61 314.57 C 342.19 323.76 336.45 332.76 331.05 341.96 C 324.62 354.04 316.79 365.31 310.38 377.39 C 305.41 384.56 301.54 392.40 296.78 399.71 C 290.29 410.33 284.30 421.24 277.99 431.97 C 267.62 447.21 259.73 463.97 249.08 479.02 C 244.35 485.33 237.50 490.71 229.49 491.80 C 223.07 492.98 216.60 490.64 210.88 487.89 C 205.68 484.07 200.75 478.79 200.12 472.05 C 199.38 464.91 199.56 456.96 203.97 450.94 C 209.04 444.01 211.63 435.67 216.66 428.72 C 221.89 421.34 225.45 412.96 230.56 405.50 C 236.11 397.24 240.85 388.50 245.75 379.85 C 257.24 361.25 268.04 342.23 279.39 323.55 C 283.37 315.67 288.11 308.22 292.72 300.71 C 299.71 290.30 305.20 278.88 313.07 269.07 C 316.98 264.08 323.33 262.12 329.35 261.14 Z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,10 @@
<svg width="722" height="722" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<g id="#70c6beff">
<path id="svg_2" d="m372.33,100.27c8.44,-1.08 16.61,3.14 22.53,8.87c6.71,6.94 11.39,15.47 16.32,23.68c62.43,104.06 124.07,208.59 186.17,312.85c14.6,24.75 29.53,49.31 43.56,74.4c6.59,11.45 9.1,25.23 6.54,38.23c-1.67,11.63 -8.97,22.12 -18.86,28.31c-7.78,4.86 -16.58,8.22 -25.73,9.17c-4.61,0.42 -9.24,0.19 -13.86,0.22c-63.67,0 -127.35,-0.01 -191.02,0c-8.07,-0.1 -16.22,-2.41 -22.78,-7.2c-7.16,-4.99 -11.59,-14.05 -10.32,-22.79c0.89,-9.17 4.85,-17.68 9.63,-25.44c10.82,-18.77 21.65,-37.53 33.15,-55.9c5.16,-8.03 9.38,-16.95 16.59,-23.43c4.87,-4.16 10.6,-7.63 16.96,-8.82c9.04,-1.12 18.19,2.51 24.97,8.39c6.95,6.16 9.53,16.17 7.88,25.14c-2.58,14.52 -13.13,25.82 -17.34,39.74c-0.92,2.35 -0.44,5.39 2.07,6.53c4.99,2.51 10.75,2.65 16.22,2.79c27.67,-0.02 55.34,-0.02 83.02,0.01c5.04,-0.14 10.92,-0.42 14.59,-4.38c1.7,-5.94 -2.55,-11.22 -5.1,-16.2c-59.46,-101.8 -118.86,-203.63 -178.93,-305.08c-2.61,-4.29 -4.77,-8.97 -8.31,-12.62c-2.33,-2.69 -7,-2.37 -8.92,0.63c-5.67,7.2 -10.1,15.27 -14.86,23.07c-65.86,110.83 -131.72,221.65 -197.58,332.48c-6.29,10.31 -11.48,21.4 -19.35,30.66c-6.28,7.48 -15.75,12.4 -25.6,12.35c-5.38,0.01 -10.4,-2.27 -15.04,-4.77c-6.95,-3.74 -12.3,-10.62 -13.5,-18.5c-1.49,-9.66 1.55,-19.46 6.41,-27.75c56.45,-95.79 113.47,-191.24 170.19,-286.88c21.72,-36.61 43.75,-73.05 65.19,-109.84c5.5,-9.12 11.24,-18.1 16.77,-27.21c6.13,-10.19 16.01,-19.5 28.34,-20.71z" fill="#70c6be"/>
</g>
<g id="#1ba0d8ff">
<path id="svg_3" d="m368.33,335.39c9.54,-1.82 19.84,0.73 27.41,6.83c5.57,5 9.37,12.21 9.55,19.78c0.61,9.39 -3.76,18.08 -8.42,25.92c-36.12,60.55 -72.06,121.21 -108.18,181.76c-5.34,8.95 -11.1,18.53 -21,23.02c-15,8.41 -36.64,-0.5 -41.29,-17.06c-1.72,-7.86 -1.04,-16.4 2.63,-23.63c7.02,-14.54 15.98,-28.02 23.94,-42.05c31.09,-52.53 62.14,-105.09 93.63,-157.38c4.97,-7.94 12.06,-15.57 21.73,-17.19z" fill="#1ba0d8"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,10 @@
<svg width="1252" height="1252" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<g id="#70c6beff">
<path id="svg_2" d="m634.37,138.38c11.88,-1.36 24.25,1.3 34.18,8.09c14.96,9.66 25.55,24.41 34.49,39.51c40.59,68.03 81.45,135.91 122.02,203.96c54.02,90.99 108.06,181.97 161.94,273.06c37.28,63 74.65,125.96 112.18,188.82c24.72,41.99 50.21,83.54 73.84,126.16c10.18,17.84 15.77,38.44 14.93,59.03c-0.59,15.92 -3.48,32.28 -11.84,46.08c-11.73,19.46 -31.39,33.2 -52.71,40.36c-11.37,4.09 -23.3,6.87 -35.43,6.89c-132.32,-0.05 -264.64,0.04 -396.95,0.03c-11.38,-0.29 -22.95,-1.6 -33.63,-5.72c-7.81,-3.33 -15.5,-7.43 -21.61,-13.42c-10.43,-10.32 -17.19,-24.96 -15.38,-39.83c0.94,-10.39 3.48,-20.64 7.76,-30.16c4.15,-9.77 9.99,-18.67 15.06,-27.97c22.13,-39.47 45.31,-78.35 69.42,-116.65c7.72,-12.05 14.44,-25.07 25.12,-34.87c11.35,-10.39 25.6,-18.54 41.21,-19.6c12.55,-0.52 24.89,3.82 35.35,10.55c11.8,6.92 21.09,18.44 24.2,31.88c4.49,17.01 -0.34,34.88 -7.55,50.42c-8.09,17.65 -19.62,33.67 -25.81,52.18c-1.13,4.21 -2.66,9.52 0.48,13.23c3.19,3 7.62,4.18 11.77,5.22c12,2.67 24.38,1.98 36.59,2.06c45,-0.01 90,0 135,0c8.91,-0.15 17.83,0.3 26.74,-0.22c6.43,-0.74 13.44,-1.79 18.44,-6.28c3.3,-2.92 3.71,-7.85 2.46,-11.85c-2.74,-8.86 -7.46,-16.93 -12.12,-24.89c-119.99,-204.91 -239.31,-410.22 -360.56,-614.4c-3.96,-6.56 -7.36,-13.68 -13.03,-18.98c-2.8,-2.69 -6.95,-4.22 -10.77,-3.11c-3.25,1.17 -5.45,4.03 -7.61,6.57c-5.34,6.81 -10.12,14.06 -14.51,21.52c-20.89,33.95 -40.88,68.44 -61.35,102.64c-117.9,198.43 -235.82,396.85 -353.71,595.29c-7.31,13.46 -15.09,26.67 -23.57,39.43c-7.45,10.96 -16.49,21.23 -28.14,27.83c-13.73,7.94 -30.69,11.09 -46.08,6.54c-11.23,-3.47 -22.09,-9.12 -30.13,-17.84c-10.18,-10.08 -14.69,-24.83 -14.17,-38.94c0.52,-14.86 5.49,-29.34 12.98,-42.1c71.58,-121.59 143.62,-242.92 215.93,-364.09c37.2,-62.8 74.23,-125.69 111.64,-188.36c37.84,-63.5 75.77,-126.94 113.44,-190.54c21.02,-35.82 42.19,-71.56 64.28,-106.74c6.79,-11.15 15.58,-21.15 26.16,-28.85c8.68,-5.92 18.42,-11 29.05,-11.94z" fill="#70c6be"/>
</g>
<g id="#1ba0d8ff">
<path id="svg_3" d="m628.35,608.38c17.83,-2.87 36.72,1.39 51.5,11.78c11.22,8.66 19.01,21.64 21.26,35.65c1.53,10.68 0.49,21.75 -3.44,31.84c-3.02,8.73 -7.35,16.94 -12.17,24.81c-68.76,115.58 -137.5,231.17 -206.27,346.75c-8.8,14.47 -16.82,29.47 -26.96,43.07c-7.37,9.11 -16.58,16.85 -27.21,21.89c-22.47,11.97 -51.79,4.67 -68.88,-13.33c-8.66,-8.69 -13.74,-20.63 -14.4,-32.84c-0.98,-12.64 1.81,-25.42 7.53,-36.69c5.03,-10.96 10.98,-21.45 17.19,-31.77c30.22,-50.84 60.17,-101.84 90.3,-152.73c41.24,-69.98 83.16,-139.55 124.66,-209.37c4.41,-7.94 9.91,-15.26 16.09,-21.9c8.33,-8.46 18.9,-15.3 30.8,-17.16z" fill="#1ba0d8"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,38 @@
From fdcb81f6ba8b8d7546a6742e9566487e12815499 Mon Sep 17 00:00:00 2001
From: sbwml <admin@cooluc.com>
Date: Thu, 28 Apr 2022 11:10:53 +0800
Subject: [PATCH] Revert "feat: clear temp file while start"
This reverts commit 24d031d57875d3c6a9624fa7334c6eac1c9111fb.
---
bootstrap/conf.go | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/bootstrap/conf.go b/bootstrap/conf.go
index 5c9a1b3..f4d87d4 100644
--- a/bootstrap/conf.go
+++ b/bootstrap/conf.go
@@ -7,7 +7,6 @@ import (
log "github.com/sirupsen/logrus"
"io/ioutil"
"os"
- "path/filepath"
)
// InitConf init config
@@ -47,11 +46,7 @@ func InitConf() {
if !conf.Conf.Force {
confFromEnv()
}
- err := os.RemoveAll(filepath.Join(conf.Conf.TempDir))
- if err != nil {
- log.Errorln("failed delete temp file:", err)
- }
- err = os.MkdirAll(conf.Conf.TempDir, 0700)
+ err := os.MkdirAll(conf.Conf.TempDir, 0700)
if err != nil {
log.Fatalf("create temp dir error: %s", err.Error())
}
--
2.34.1

View File

@ -1,52 +0,0 @@
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=app-store-ui
PKG_VERSION:=1.0
PKG_RELEASE:=10
PKG_HOST_ONLY=1
HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/${PKG_NAME}
include $(INCLUDE_DIR)/host-build.mk
include $(INCLUDE_DIR)/package.mk
define Package/app-store-ui
SECTION:=libs
CATEGORY:=Libraries
TITLE:=App Store UI
BUILDONLY:=1
endef
define Package/app-store-ui/description
UI for luci-app-store
endef
define Host/Prepare
mkdir -p $(HOST_BUILD_DIR)
$(CP) ./src/. $(HOST_BUILD_DIR)
find $(HOST_BUILD_DIR) -name .svn | $(XARGS) rm -rf
endef
define Host/Configure
endef
define Host/Compile
endef
define Host/Install
endef
define Host/Clean
rm -f $(HOST_BUILD_DIR)/src/dist
endef
$(eval $(call HostBuild))
$(eval $(call BuildPackage,app-store-ui))

View File

@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script type="module" crossorigin src="/luci-static/istore/index.js"></script>
<link rel="modulepreload" href="/luci-static/istore/vendor.js?v=64c6a109">
<link rel="stylesheet" href="/luci-static/istore/style.css">
</head>
<body>
<script>
(function(){
var vue_prefix="<%=prefix%>";
var myurl = window.location.pathname;
window.addEventListener('popstate', () => {
if (myurl != window.location.pathname
&& window.location.pathname != vue_prefix
&& ! window.location.pathname.startsWith(vue_prefix+'/')) {
window.location.href = window.location.pathname;
}
});
window.vue_base = vue_prefix + '/';
window.vue_lang_data = '/luci-static/istore/i18n/<%=lang%>.json?v=<%=id.version%>';
window.vue_lang = '<%=lang%>';
window.token = "<%=token%>";
window.device_id = {arch:"<%=id.arch%>",uid:"<%=id.uid%>",version:"<%=id.version%>"};
})();
</script>
<h2 name="content">iStore dev</h2>
<div id="app"></div>
</body>
</html>

View File

@ -1 +0,0 @@
{"en":{"%{ num } download":["%{ num } download","%{ num } downloads"],"%{ num } like":["%{ num } like","%{ num } likes"],"all app":"all app","app backup":"app backup","are you sure you want to uninstall %{name}?":"are you sure you want to uninstall %{name}?","author":"author","backup fail":"backup fail","backup fail with error code":"backup fail with error code","backup now":"backup now","backup now backs up installed software (unlimited installation sources) to external storage":"backup now backs up installed software (unlimited installation sources) to external storage","backup now will download a list of iStore installed software":"backup now will download a list of iStore installed software","backup success":"backup success","backuping":"backuping","By download":"By download","By rating":"By rating","checking for latest version":"checking for latest version","choose":"choose","choose backup file":"choose backup file","click to download":"click to download","click to update":"click to update","closed":"closed","customize":"customize","default":"default","Docker is not installed on the system, try to install it?":"Docker is not installed on the system, try to install it?","download":"Download","explain":"explain","external storage directory":"external storage directory","Icon is gone":"Icon is gone","install":"install","installation failed, error code":"installation failed, error code","installed":"installed","last version":"last version","light backup":"light backup","like":"like","liked":"liked","loading data":"loading data","local backup":"local backup","maintain":"maintain","manual install":"manual install","monitor":"Monitor","multimedia":"Multimedia","nas":"NAS","net":"Net","networking":"Networking","no files selected":"no files selected","no internet required for recovery":"no internet required for recovery","offline install":"offline install","offline installation failed with error code":"offline installation failed with error code","open":"open","order":"order","packages installed offline may not appear in iStore":"packages installed offline may not appear in iStore","please enter an absolute path starting with %{name}":"please enter an absolute path starting with %{name}","please enter the path, give up the input, please clear the input box":"please enter the path, give up the input, please clear the input box","please enter the search keyword":"please enter the search keyword","please fill in the external storage directory":"please fill in the external storage directory","please select a backup file to restore":"please select a backup file to restore","restore backup":"restore backup","restore failed with error code":"restore failed with error code","restore now":"restore now","select or drag and drop files":"select or drag and drop files","service":"Service","Stick to the top":"Stick to the top","supports .ipk packages, .run self-extracting packages":"supports .ipk packages, .run self-extracting packages","system":"System","tag":"Tag","the is last version":"the is last version","there are no backup files in this path":"there are no backup files in this path","tool":"Tool","uninstall":"uninstall","uninstall failed, error code":"uninstall failed, error code","update date":"update date","update error":"update error","update failed with error code":"update failed with error code","update success, reloading":"update success, reloading","updateing":"updateing","upgrade":"upgrade","upload software list and install from iStore when restoring backup":"upload software list and install from iStore when restoring backup","uploading":"uploading","website":"website","you have already liked":"you have already liked"}}

View File

@ -1 +0,0 @@
{"zh-cn":{"%{ num } download":["%{ num } 次下载","%{ num } 次下载"],"%{ num } like":["%{ num } 次点赞","%{ num } 次点赞"],"all app":"全部软件","app backup":"软件备份","are you sure you want to uninstall %{name}?":"确定要卸载 %{name} 吗?","author":"作者","backup fail":"备份失败","backup fail with error code":"备份失败,错误代码","backup now":"立即备份","backup now backs up installed software (unlimited installation sources) to external storage":"立即备份将备份已安装软件(不限安装来源)到外部存储","backup now will download a list of iStore installed software":"立即备份将下载iStore已安装的软件列表","backup success":"备份成功","backuping":"正在备份","By download":"按下载","By rating":"按评分","checking for latest version":"正在检查最新版本","choose":"请选择","choose backup file":"选择备份文件","click to download":"点此下载","click to update":"点我更新","closed":"关闭","customize":"自定义","default":"默认","Docker is not installed on the system, try to install it?":"系统中未安装Docker是否尝试安装","download":"下载","explain":"说明","external storage directory":"外部存储目录","Icon is gone":"图标出走啦","in this page, you can upload and install packages":"通过本页面,你可以上传并安装插件包","install":"安装","installation failed, error code":"安装失败,错误码","installed":"已安装","last version":"最新版本","light backup":"轻量备份","like":"点赞","liked":"已点赞","loading data":"正在努力的获取数据","local backup":"本地备份","maintain":"维护","manual install":"手动安装","monitor":"监控","multimedia":"多媒体","nas":"NAS","net":"网络","networking":"组网","no files selected":"未选择任何文件","no internet required for recovery":"恢复时不需要网络","offline install":"离线安装","offline installation failed with error code":"离线安装失败,错误码","open":"打开","order":"排序","packages installed offline may not appear in iStore":"离线安装的插件可能不会出现在iStore中","please enter an absolute path starting with %{name}":"请输入 %{name} 开头的绝对路径","please enter the path, give up the input, please clear the input box":"请输入路径,放弃输入请清空输入框","please enter the search keyword":"请输入搜索关键词","please fill in the external storage directory":"请填写外部存储目录","please select a backup file to restore":"请选择要恢复的备份文件","restore backup":"恢复备份","restore failed with error code":"恢复失败,错误代码","restore now":"立即恢复","select or drag and drop files":"选择或拖放文件","service":"服务","Stick to the top":"置顶","supports .ipk packages, .run self-extracting packages":"支持 .ipk 包,.run 自解压格式","system":"系统","tag":"标签","the is last version":"当前已经是最新版本","there are no backup files in this path":"此路径下没有备份文件","tool":"工具","uninstall":"卸载","uninstall failed, error code":"卸载失败,错误码","update date":"更新日期","update error":"更新失败","update failed with error code":"更新失败,错误代码","update success, reloading":"更新成功,重新加载页面","updateing":"正在更新中","upgrade":"更新","upload software list and install from iStore when restoring backup":"复备份时上传软件列表并从iStore安装","uploading":"上传中","website":"官网","you have already liked":"您已经点赞过啦"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

223
ffmpeg-remux/Makefile Normal file
View File

@ -0,0 +1,223 @@
#
# Copyright (C) 2017-2020 Ian Leonard <antonlacon@gmail.com>
# Copyright (C) 2018 Ted Hess <thess@kitschensync.net>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=ffmpeg-remux
PKG_VERSION:=4.3.3
PKG_RELEASE:=1
PKG_SOURCE:=ffmpeg-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://ffmpeg.org/releases/
PKG_HASH:=9f0a68fbd74feb4e50dc220bddd59d84626774a53687fb737806ae00e5c6e9e6
PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>, \
Ian Leonard <antonlacon@gmail.com>
PKG_LICENSE:=LGPL-2.1-or-later GPL-2.0-or-later LGPL-3.0-or-later
PKG_LICENSE_FILES:=COPYING.GPLv2 COPYING.GPLv3 COPYING.LGPLv2.1 COPYING.LGPLv3
PKG_CPE_ID:=cpe:/a:ffmpeg:ffmpeg
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-x/ffmpeg-$(PKG_VERSION)
FFMPEG_REMUX_DECODERS:= \
mpeg1video \
mpeg2video \
mpeg4 \
mpegvideo \
h264 \
hevc \
vc1 \
FFMPEG_REMUX_MUXERS:= \
matroska \
h264 \
hevc \
mp4 \
mpeg1video \
mpeg2video \
mpegts \
ogg \
FFMPEG_REMUX_DEMUXERS:= \
avi \
h264 \
hevc \
matroska \
mov \
mpegps \
mpegts \
mpegvideo \
ogg \
rm \
vc1 \
wv \
FFMPEG_REMUX_PARSERS:= \
aac \
flac \
ac3 \
h264 \
hevc \
mpegaudio \
mpeg4video \
mpegvideo \
vc1 \
FFMPEG_REMUX_PROTOCOLS:= \
file pipe
include $(INCLUDE_DIR)/package.mk
define Package/ffmpeg-remux
TITLE:=FFmpeg remux
SECTION:=multimedia
CATEGORY:=Multimedia
URL:=https://ffmpeg.org/
DEPENDS+= +libpthread +zlib +libbz2
endef
define Package/ffmpeg-remux/description
FFmpeg remux only program
endef
# Strip off FPU notation
REAL_CPU_TYPE:=$(firstword $(subst +, ,$(CONFIG_CPU_TYPE)))
# Fixup cpu types recogized by ffmpeg configure
REAL_CPU_TYPE:=$(subst octeonplus,octeon+,$(REAL_CPU_TYPE))
FFMPEG_CONFIGURE:= \
CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(FPIC)" \
LDFLAGS="$(TARGET_LDFLAGS)" \
./configure \
--enable-cross-compile \
--cross-prefix="$(TARGET_CROSS)" \
--arch="$(ARCH)" \
$(if $(REAL_CPU_TYPE),--cpu=$(call qstrip,$(REAL_CPU_TYPE)),) \
--target-os=linux \
--prefix="/usr" \
--pkg-config="pkg-config" \
--enable-shared \
--enable-pthreads \
--enable-zlib \
--disable-doc \
--disable-debug \
\
--disable-lzma \
--disable-vaapi \
--disable-vdpau \
--disable-outdevs
ifeq ($(CONFIG_SOFT_FLOAT),y)
FFMPEG_CONFIGURE+= \
--disable-altivec \
--disable-vsx \
--disable-power8 \
--disable-armv5te \
--disable-armv6 \
--disable-armv6t2 \
--disable-fast-unaligned \
--disable-runtime-cpudetect
else ifneq ($(findstring arm,$(CONFIG_ARCH))$(findstring aarch64,$(CONFIG_ARCH)),)
FFMPEG_CONFIGURE+= \
--disable-runtime-cpudetect
# XXX: GitHub issue 3320 ppc cpu with fpu but no altivec (WNDR4700)
else ifneq ($(findstring powerpc,$(CONFIG_ARCH)),)
FFMPEG_CONFIGURE+= \
--disable-altivec
endif
# selectively disable optimizations according to arch/cpu type
ifneq ($(findstring arm,$(CONFIG_ARCH)),)
FFMPEG_CONFIGURE+= --enable-lto
ifneq ($(findstring vfp,$(CONFIG_CPU_TYPE)),)
FFMPEG_CONFIGURE+= --enable-vfp
else
FFMPEG_CONFIGURE+= --disable-vfp
endif
ifneq ($(findstring neon,$(CONFIG_CPU_TYPE)),)
FFMPEG_CONFIGURE+= \
--enable-neon \
--enable-vfp
else
FFMPEG_CONFIGURE+= --disable-neon
endif
endif
ifneq ($(findstring aarch64,$(CONFIG_ARCH)),)
FFMPEG_CONFIGURE+= \
--enable-lto \
--enable-neon \
--enable-vfp
endif
ifeq ($(ARCH),x86_64)
FFMPEG_CONFIGURE+= --enable-lto
endif
ifeq ($(CONFIG_FFMPEG_X86ASM),y)
FFMPEG_CONFIGURE += --enable-x86asm
else
FFMPEG_CONFIGURE += --disable-x86asm
endif
FFMPEG_ENABLE= \
$(foreach c, $(2), \
--enable-$(1)="$(c)" \
)
FFMPEG_CONFIGURE+= \
--enable-hardcoded-tables \
--disable-static \
--libdir="/usr/lib/remux" \
--enable-rpath \
\
--disable-ffplay \
--disable-alsa \
--disable-iconv \
--disable-sndio \
--disable-schannel \
--disable-sdl2 \
--disable-securetransport \
--disable-xlib \
--disable-v4l2-m2m \
--disable-avdevice \
--disable-postproc \
--disable-swresample \
--disable-swscale \
--disable-everything \
$(call FFMPEG_ENABLE,decoder,$(FFMPEG_REMUX_DECODERS)) \
$(call FFMPEG_ENABLE,parser,$(FFMPEG_REMUX_PARSERS)) \
$(call FFMPEG_ENABLE,demuxer,$(FFMPEG_REMUX_DEMUXERS)) \
$(call FFMPEG_ENABLE,muxer,$(FFMPEG_REMUX_MUXERS)) \
$(call FFMPEG_ENABLE,protocol,$(FFMPEG_REMUX_PROTOCOLS))
ifneq ($(CONFIG_TARGET_x86),)
TARGET_CFLAGS+= -fomit-frame-pointer
endif
define Build/Configure
( cd $(PKG_BUILD_DIR); $(FFMPEG_CONFIGURE) )
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
DESTDIR="$(PKG_INSTALL_DIR)" \
all install
endef
define Package/ffmpeg-remux/install
$(INSTALL_DIR) $(1)/usr/lib/remux
$(INSTALL_DIR) $(1)/usr/bin
$(CP) $(PKG_INSTALL_DIR)/usr/lib/remux/lib{avcodec,avfilter,avformat,avutil}.so.* $(1)/usr/lib/remux/
$(CP) $(PKG_INSTALL_DIR)/usr/bin/ffmpeg $(1)/usr/bin/remux
endef
$(eval $(call BuildPackage,ffmpeg-remux))

29
luci-app-alist/Makefile Normal file
View File

@ -0,0 +1,29 @@
# Copyright (C) 2016 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-alist
PKG_VERSION:=1.0.4
PKG_RELEASE:=1
LUCI_TITLE:=LuCI support for alist
LUCI_DEPENDS:=+alist +luci-compat
define Package/$(PKG_NAME)/conffiles
/etc/alist
endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
[ -n "${IPKG_INSTROOT}" ] || {
( . /etc/uci-defaults/luci-alist ) && rm -f /etc/uci-defaults/luci-alist
exit 0
}
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,25 @@
module("luci.controller.alist", package.seeall)
function index()
if not nixio.fs.access("/etc/config/alist") then
return
end
entry({"admin", "nas"}, firstchild(), "NAS", 44).dependent = false
entry({"admin", "nas", "alist"}, cbi("alist"), _("Alist"), 20).dependent = true
entry({"admin", "nas", "alist_status"}, call("alist_status"))
end
function alist_status()
local sys = require "luci.sys"
local uci = require "luci.model.uci".cursor()
local port = tonumber(uci:get_first("alist", "alist", "port"))
local status = {
running = (sys.call("pidof alist >/dev/null") == 0),
port = (port or 5244)
}
luci.http.prepare_content("application/json")
luci.http.write_json(status)
end

View File

@ -0,0 +1,53 @@
local m, s
local sys = require "luci.sys"
if sys.call("pidof alist >/dev/null") == 0 then
local password = sys.exec("/usr/bin/alist --conf /etc/alist/config.json -password | awk '{print $3}'")
m = Map("alist", translate("Alist"), translate("A file list program that supports multiple storage.") .. " " .. translate("manage password:") .. "<font color=\"green\">" .. password .. "</font>" .. "<br/>" .. [[<a href="https://alist-doc.nn.ci/docs/driver/native" target="_blank">]] .. translate("User Manual") .. [[</a>]])
else
m = Map("alist", translate("Alist"), translate("A file list program that supports multiple storage.") .. "<br/>" .. [[<a href="https://alist-doc.nn.ci/docs/driver/native" target="_blank">]] .. translate("User Manual") .. [[</a>]])
end
m:section(SimpleSection).template = "alist_status"
s = m:section(TypedSection, "alist", translate("Global settings"))
s.addremove = false
s.anonymous = true
o = s:option(Flag, "enabled", translate("Enable"))
o.rmempty = false
o = s:option(Value, "port", translate("Port"))
o.datatype = "and(port,min(1))"
o.rmempty = false
o = s:option(Flag, "ssl", translate("Enable SSL"))
o.rmempty=false
o = s:option(Value,"ssl_cert", translate("SSL cert"), translate("SSL certificate file path"))
o:depends("ssl", "1")
o.datatype = "string"
o.rmempty = true
o = s:option(Value,"ssl_key", translate("SSL key"), translate("SSL key file path"))
o:depends("ssl", "1")
o.datatype = "string"
o.rmempty = true
s = m:section(TypedSection, "alist", translate("Cache settings"))
s.addremove = false
s.anonymous = true
o = s:option(Value, "expiration", translate("Cache invalidation time (unit: minutes)"))
o.datatype = "and(uinteger,min(1))"
o.rmempty = false
o = s:option(Value, "cleanup_interval", translate("Clear the invalidation cache interval (unit: minutes)"))
o.datatype = "and(uinteger,min(1))"
o.rmempty = false
o = s:option(Value, "temp_dir", translate("Cache directory"))
o.datatype = "string"
o.rmempty = false
return m

View File

@ -0,0 +1,36 @@
<%
local uci = require 'luci.model.uci'.cursor()
ssl = uci:get_first('alist', 'alist', 'ssl')
if ssl == '1' then
protocol="https://"
else
protocol="http://"
end
%>
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=url("admin/nas/alist_status")%>', null,
function(x, st)
{
var tb = document.getElementById('alist_status');
if (st && tb)
{
if (st.running)
{
tb.innerHTML = '<em style=\"color:green\"><b><%:The Alist service is running.%></b></em>' + "<input class=\"cbi-button-reload mar-10\" type=\"button\" value=\" <%:Click to open Alist%> \" onclick=\"window.open('<%=protocol%>" + window.location.hostname + ":" + st.port + "/')\"/>";
}
else
{
tb.innerHTML = '<em style=\"color:red\"><b><%:The Alist service is not running.%></b></em>';
}
}
}
);
//]]></script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="alist_status">
<em><b><%:Collecting data...%></b></em>
</p>
</fieldset>

View File

@ -0,0 +1,62 @@
msgid "Alist"
msgstr "Alist 文件列表"
msgid "Running state"
msgstr "运行状态"
msgid "Click to open Alist"
msgstr "点击打开 Alist"
msgid "A file list program that supports multiple storage."
msgstr "一款支持多种存储的目录文件列表程序。"
msgid "manage password:"
msgstr "管理密码:"
msgid "Global settings"
msgstr "全局设置"
msgid "Port"
msgstr "端口"
msgid "Enable SSL"
msgstr "启用 SSL"
msgid "SSL cert"
msgstr "SSL 证书"
msgid "SSL certificate file path"
msgstr "SSL 证书文件路径"
msgid "SSL key"
msgstr "SSL 密钥"
msgid "SSL key file path"
msgstr "SSL 密钥文件路径"
msgid "Cache settings"
msgstr "缓存设置"
msgid "Cache invalidation time (unit: minutes)"
msgstr "缓存失效时间(分钟)"
msgid "Clear the invalidation cache interval (unit: minutes)"
msgstr "清理失效缓存间隔(分钟)"
msgid "Cache directory"
msgstr "缓存目录"
msgid "The Alist service is running."
msgstr "Alist 服务已启动"
msgid "The Alist service is not running."
msgstr "Alist 服务未启动"
msgid "Collecting data..."
msgstr "收集数据..."
msgid "NAS"
msgstr "网络存储"
msgid "User Manual"
msgstr "用户手册"

1
luci-app-alist/po/zh_Hans Symbolic link
View File

@ -0,0 +1 @@
zh-cn

Binary file not shown.

View File

@ -0,0 +1,7 @@
config alist
option 'enabled' '0'
option 'port' '5244'
option 'expiration' '60'
option 'cleanup_interval' '120'
option 'temp_dir' '/tmp'
option 'ssl' '0'

View File

@ -0,0 +1,48 @@
#!/bin/sh /etc/rc.common
START=99
USE_PROCD=1
PROG=/usr/bin/alist
CONFIG=/etc/alist/config.json
get_config() {
config_get_bool enabled $1 enabled 1
config_get port $1 port 5244
config_get expiration $1 expiration 60
config_get cleanup_interval $1 cleanup_interval 120
config_get temp_dir $1 temp_dir "/tmp"
config_get ssl $1 ssl 0
config_get ssl_cert $1 ssl_cert ""
config_get ssl_key $1 ssl_key ""
}
start_service() {
config_load alist
config_foreach get_config alist
[ $enabled != 1 ] && return 1
mkdir -p $temp_dir
if [ "$ssl" -eq 1 ];then
SSL=true
else
SSL=false
fi
cat > $CONFIG <<EOF
{"address":"0.0.0.0","port":$port,"assets":"/","database":{"type":"sqlite3","user":"","password":"","host":"","port":0,"name":"","table_prefix":"x_","db_file":"/etc/alist/data.db","ssl_mode":"disable"},"scheme":{"https":$SSL,"cert_file":"$ssl_cert","key_file":"$ssl_key"},"cache":{"expiration":$expiration,"cleanup_interval":$cleanup_interval},"temp_dir":"$temp_dir"}
EOF
procd_open_instance alist
procd_set_param command $PROG
procd_append_param command --conf $CONFIG
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param respawn
procd_close_instance alist
}
service_triggers() {
procd_add_reload_trigger "alist"
}
reload_service() {
stop
start
}

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@alist[-1]
add ucitrack alist
set ucitrack.@alist[-1].init=alist
commit ucitrack
EOF
rm -rf /tmp/luci-*
exit 0

View File

@ -0,0 +1,11 @@
{
"luci-app-alist": {
"description": "Grant UCI access for luci-app-alist",
"read": {
"uci": [ "alist" ]
},
"write": {
"uci": [ "alist" ]
}
}
}

View File

@ -16,7 +16,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-amlogic
PKG_VERSION:=3.1.121
PKG_VERSION:=3.1.122
PKG_RELEASE:=1
PKG_LICENSE:=GPL-2.0 License

View File

@ -113,6 +113,12 @@ check_kernel() {
# Determine custom kernel filename
kernel_boot="$(ls boot-*.tar.gz | head -n 1)"
kernel_name="${kernel_boot/boot-/}" && kernel_name="${kernel_name/.tar.gz/}"
# check if kernel is locked
if [[ "${LOCK_KERNEL}" != "${kernel_name}" ]];then
error_msg "The kernel version is locked to ${LOCK_KERNEL}. "
fi
KERNEL_VERSION="$(echo ${kernel_name} | grep -oE '^[1-9].[0-9]{1,3}.[0-9]+')"
echo -e "Kernel name: ${kernel_name}"
@ -123,6 +129,7 @@ check_kernel() {
[[ -n "${UBOOT_OVERLOAD}" && -f "/boot/${UBOOT_OVERLOAD}" ]] || error_msg "The UBOOT_OVERLOAD file is missing and cannot be update."
fi
# Check the sha256sums file
sha256sums_file="sha256sums"
sha256sums_check="1"

View File

@ -48,6 +48,13 @@ elif [[ "$(echo ${MYDEVICE_NAME} | grep "FastRhino R68S")" != "" ]]; then
MYDTB_FDTFILE="rk3568-fastrhino-r68s.dtb"
fi
SOC="r68s"
elif [[ "$(echo ${MYDEVICE_NAME} | grep "Radxa ROCK 5B")" != "" ]]; then
if [ -n "$CURRENT_FDTFILE" ];then
MYDTB_FDTFILE="$CURRENT_FDTFILE"
else
MYDTB_FDTFILE="rk3588-rock-5b.dtb"
fi
SOC="rock5b"
else
echo "Unknown device: [ ${MYDEVICE_NAME} ], Not supported."
exit 1
@ -67,7 +74,12 @@ case ${ROOT_PTNAME} in
mmcblk?p[1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
PARTITION_NAME="p"
LB_PRE="EMMC_"
LB_PRE="MMC_"
;;
nvme?n?p?)
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-2)}')
PARTITION_NAME="p"
LB_PRE="NVME_"
;;
[hsv]d[a-z][1-4])
EMMC_NAME=$(echo ${ROOT_PTNAME} | awk '{print substr($1, 1, length($1)-1)}')
@ -573,6 +585,8 @@ cd ${WORK_DIR}
echo "Start copy data from ${P2} to /boot ..."
cd /boot
echo -n "backup armbianEnv.txt ..."
cp armbianEnv.txt /tmp/
echo -n "remove old boot files ..."
rm -rf *
echo "done"
@ -583,19 +597,27 @@ echo "done"
echo
echo -n "Update boot args ... "
cat >armbianEnv.txt <<EOF
verbosity=7
overlay_prefix=rockchip
if [ -f /tmp/armbianEnv.txt ];then
cp /tmp/armbianEnv.txt .
fi
sed -e '/fdtfile=/d' -i armbianEnv.txt
sed -e '/rootdev=/d' -i armbianEnv.txt
sed -e '/rootfstype=/d' -i armbianEnv.txt
sed -e '/rootflags=/d' -i armbianEnv.txt
if [ "$SOC" == "rock5b" ];then
echo "fdtfile=rockchip/${MYDTB_FDTFILE}" >> armbianEnv.txt
else
echo "fdtfile=/dtb/rockchip/${MYDTB_FDTFILE}" >> armbianEnv.txt
fi
cat >> armbianEnv.txt <<EOF
rootdev=UUID=${NEW_ROOT_UUID}
rootfstype=btrfs
rootflags=compress=zstd:${ZSTD_LEVEL}
extraargs=usbcore.autosuspend=-1 net.ifnames=0
extraboardargs=
fdtfile=/dtb/rockchip/${MYDTB_FDTFILE}
EOF
# 对没有 HDMI 的机型关闭 display tty 让 initrd script 输出到 uart
# 参考 https://github.com/raspberrypi/linux/issues/2863
if [ "$SOC" == "r68s" ];then
sed -e '/console=/d' -i armbianEnv.txt
echo console=serial >> armbianEnv.txt
fi
sync

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,18 @@
# Copyright (C) 2021 2021 ZeaKyX
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-speedtest-web
LUCI_TITLE:=LuCI support for speedtest-web
LUCI_DEPENDS:=+speedtest-web
LUCI_PKGARCH:=all
PKG_VERSION:=1.0
PKG_RELEASE:=1
PKG_MAINTAINER:=<https://github.com/ZeaKyX/luci-app-speedtest-web>
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,26 @@
# luci-app-speedtest-web
LuCI support for speedtest-web 内网测速网页版
# 简介
<s>还在为不会iperf命令行测速而担忧吗</s>
- **在 OpenWRT/LEDE 上进行网页内网测速的插件**
- 一键测速,简单易用
- 代码很烂抛砖引玉欢迎PR
# 使用截图
![image](https://github.com/ZeaKyX/luci-app-speedtest-web/blob/main/img/img.gif)
# 下载
- [luci-app-speedtest-web](https://github.com/ZeaKyX/luci-app-speedtest-web/releases)
# TODO
- 加强配置文件:设置端口号、测速时长...
- 添加设置页面(?)
- 添加启动/关闭开关(?)
- 黑暗主题自适应
- 定制测速页面
- ...
# 鸣谢
- Lean的各种[软件包](https://github.com/coolsnowwolf/lede/tree/master/package/lean),让我缝!
- LibreSpeed的Go维护[speedtest-go](https://github.com/librespeed/speedtest-go)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

@ -0,0 +1,9 @@
module("luci.controller.speedtest-web", package.seeall)
function index()
if not (luci.sys.call("pidof speedtest-web > /dev/null") == 0) then
return
end
entry({"admin", "network", "speedtest-web"}, template("speedtest-web/speedtest-web"), _("Speedtest Web"), 10).leaf = true
end

View File

@ -0,0 +1,13 @@
<%+header%>
<div class="cbi-map">
<h2 name="content"><%=translate("Speedtest Web")%></h2>
<iframe id="speedtest-web" style="width: 100%; min-height: 500px; border: none; border-radius: 3px;"></iframe>
</div>
<script type="text/javascript">
document.getElementById("speedtest-web").src = window.location.protocol + "//" + window.location.hostname + ":8989";
document.getElementById("speedtest-web").height = document.documentElement.clientHeight;
window.onresize = function(){
document.getElementById("speedtest-web").height = document.documentElement.clientHeight;
}
</script>
<%+footer%>

View File

@ -0,0 +1,5 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Speedtest Web"
msgstr "内网测速网页版"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,4 @@
config speedtest-web 'config'
option enabled '1'
option port '8989'

View File

@ -0,0 +1,19 @@
#!/bin/sh /etc/rc.common
START=90
STOP=10
enabled="$(uci get speedtest-web.config.enabled)"
port="$(uci get speedtest-web.config.port)"
start() {
stop
[ "$enabled" == "1" ] || exit 0
speedtest-web \
--listen_port "${port}" \
>/dev/null 2>&1 &
}
stop() {
killall speedtest-web >/dev/null 2>&1
}

View File

@ -0,0 +1,11 @@
{
"luci-app-speedtest-web": {
"description": "Grant UCI access for luci-app-speedtest-web",
"read": {
"uci": [ "speedtest-web" ]
},
"write": {
"uci": [ "speedtest-web" ]
}
}
}

20
luci-lib-taskd/Makefile Normal file
View File

@ -0,0 +1,20 @@
#
# Copyright (C) 2022 jjm2473 <jjm2473@gmail.com>
#
# This is free software, licensed under the MIT License.
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Task library
LUCI_DEPENDS:=+luci-lib-xterm +taskd
LUCI_EXTRA_DEPENDS:=taskd (>=1.0.3-1)
LUCI_PKGARCH:=all
PKG_VERSION:=1.0.17
PKG_RELEASE:=
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,112 @@
[hidden] {
display: none !important;
}
#tasks_detail_container {
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: #0008;
}
#tasks_dialog {
position: absolute;
width: 770px;
max-width: 100%;
max-height: 100%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #000;
border-radius: 10px;
box-shadow: 2px 2px 6px #000a;
padding: 20px;
color: white;
}
.dialog-title-bar {
margin-top: -10px;
margin-right: -10px;
margin-bottom: 5px;
display: flex;
flex-direction: row;
justify-content: space-between;
flex-wrap: nowrap;
align-items: center;
}
.dialog-title-bar .dialog-title {
word-break: break-all;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.dialog-content {
max-height: 500px;
overflow-y: scroll;
margin-right: -10px;
}
.dialog-icons {
align-self: center;
display: flex;
justify-content: flex-end;
}
.dialog-icon {
display: flex;
align-items: center;
flex-wrap: nowrap;
width: 20px;
height: 20px;
background-color: white;
color: black;
border-radius: 50%;
font-size: 10px;
font-weight: bold;
user-select: none;
margin-left: 10px;
line-height: 1;
font-family: sans-serif;
justify-content: center;
cursor: pointer;
}
.dialog-icon.dialog-icon-min {
background-color: darkorange;
}
.dialog-icon.dialog-icon-close {
background-color: #ff5f56;
}
.dialog-icons:hover .dialog-icon.dialog-icon-min:before {
content: "_";
}
.dialog-icons:hover .dialog-icon.dialog-icon-close:before {
content: "X";
}
.tasks_stopped .dialog-icon.dialog-icon-close {
background-color: #27c840;
}
.tasks_stopped #tasks_dialog, .tasks_unknown #tasks_dialog {
padding: 19px;
border: 1px #27c840 solid;
animation: border-blink 1s;
animation-iteration-count: infinite;
}
.tasks_failed #tasks_dialog {
border-color: #ff0000;
}
.tasks_failed .dialog-icon.dialog-icon-close {
background-color: #ff0000;
}
.tasks_unknown #tasks_dialog {
border-color: darkorange;
}
@keyframes border-blink { 50% { border-color:#fff ; } }

View File

@ -0,0 +1,232 @@
(function(){
const taskd={};
const $gettext = function(str) {
return taskd.i18n[str] || str;
};
const retryPromise = function(fn) {
return new Promise((resolve, reject) => {
const retry = function() {
fn(resolve, reject, retry);
};
retry();
});
};
const retry403XHR = function(url, method, responseType) {
return retryPromise((resolve, reject, retry) => {
var oReq = new XMLHttpRequest();
oReq.onerror = reject;
oReq.open(method || 'GET', url, true);
if (responseType) {
oReq.responseType = responseType;
}
oReq.onload = function (oEvent) {
if (oReq.status == 403) {
alert($gettext("Lost login status"));
location.href = location.href;
} else if (oReq.status == 404) {
reject(oEvent);
} else {
resolve(oReq);
}
};
if (method=='POST') {
oReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
}
oReq.send(method=='POST'?("token="+taskd.csrfToken):null);
});
};
const request = function(url, method) {
return retry403XHR(url, method).then(oReq => oReq.responseText);
};
const getBin = function(url) {
return retry403XHR(url, null, "arraybuffer").then(oReq => {return {status: oReq.status, buffer: new Uint8Array(oReq.response)}});
};
const getTaskDetail = function(task_id) {
return request("/cgi-bin/luci/admin/system/tasks/status?task_id="+task_id).then(data=>JSON.parse(data));
};
const create_dialog = function(cfg) {
const container = document.createElement('div');
container.id = "tasks_detail_container";
container.innerHTML = taskd.dialog_template;
document.body.appendChild(container);
const title_view = container.querySelector(".dialog-title-bar .dialog-title");
title_view.innerText = cfg.title;
const term = new Terminal({convertEol: cfg.convertEol||false});
if (cfg.nohide) {
container.querySelector(".dialog-icon-min").hidden = true;
} else {
container.querySelector(".dialog-icon-min").onclick = function(){
container.hidden=true;
term.dispose();
document.body.removeChild(container);
cfg.onhide && cfg.onhide();
return false;
};
}
term.open(document.getElementById("tasks_xterm_log"));
return {term,container};
};
const show_log_txt = function(title, content, onclose) {
const dialog = create_dialog({title, convertEol:true, onhine:onclose});
const container = dialog.container;
const term = dialog.term;
container.querySelector(".dialog-icon-close").hidden = true;
term.write(content);
};
const show_log = function(task_id, nohide) {
let showing = true;
let running = true;
const dialog = create_dialog({title:task_id, nohide, onhide:function(){showing=false;}});
const container = dialog.container;
const term = dialog.term;
const title_view = container.querySelector(".dialog-title-bar .dialog-title");
container.querySelector(".dialog-icon-close").onclick = function(){
if (!running || confirm($gettext("Stop running task?"))) {
running=false;
showing=false;
del_task(task_id).then(()=>{
location.href = location.href;
});
}
return false;
};
const checkTask = function() {
return getTaskDetail(task_id).then(data=>{
if (!running) {
return false;
}
running = data.running;
let title = task_id;
if (!data.running && data.stop) {
title += " (" + (data.exit_code?$gettext("Failed at:"):$gettext("Finished at:")) + " " + new Date(data.stop * 1000).toLocaleString() + ")";
}
title += " > " + (data.command || '');
title_view.title = title;
title_view.innerText = title;
if (!data.running) {
container.classList.add('tasks_stopped');
if (data.exit_code) {
container.classList.add('tasks_failed');
}
}
// last pull
return showing;
});
};
let logoffset = 0;
const pulllog = function(check) {
let starter = Promise.resolve(showing);
if (check) {
starter = checkTask();
}
starter.then(again => {
if (again)
return getBin("/cgi-bin/luci/admin/system/tasks/log?task_id="+task_id+"&offset="+logoffset);
else
return {status: 204};
}).then(function(res){
if (!showing) {
return false;
}
switch(res.status){
case 205:
term.reset();
logoffset = 0;
return running;
break;
case 204:
return running && checkTask();
break;
case 200:
logoffset += res.buffer.byteLength;
term.write(res.buffer);
return running;
break;
}
}).then(again => {
if (again) {
setTimeout(pulllog, 0);
}
}).catch(err => {
if (showing) {
if (err.target.status == 0) {
title_view.innerText = task_id + ' (' + $gettext("Fetch log failed, retrying...") + ')';
setTimeout(()=>pulllog(true), 1000);
} else if (err.target.status == 403 || err.target.status == 404) {
title_view.innerText = task_id + ' (' + $gettext(err.target.status == 403?"Lost login status":"Task does not exist or has been deleted") + ')';
container.querySelector(".dialog-icon-close").hidden = true;
container.classList.add('tasks_unknown');
} else {
console.error(err);
}
}
});
};
pulllog(true);
};
const del_task = function(task_id) {
return request("/cgi-bin/luci/admin/system/tasks/stop?task_id="+task_id, "POST");
};
taskd.show_log = show_log;
taskd.remove = del_task;
taskd.show_log_txt = show_log_txt;
window.taskd=taskd;
})();
(function(){
// compat
if (typeof(window.findParent) !== 'function') {
const elem = function(e) {
return (e != null && typeof(e) == 'object' && 'nodeType' in e);
};
const matches = function(node, selector) {
var m = elem(node) ? node.matches || node.msMatchesSelector : null;
return m ? m.call(node, selector) : false;
};
window.findParent = function (node, selector) {
if (elem(node) && node.closest)
return node.closest(selector);
while (elem(node))
if (matches(node, selector))
return node;
else
node = node.parentNode;
return null;
};
}
if (typeof(window.cbi_submit) !== 'function') {
const makeHidden = function(name) {
const input = document.createElement('input');
input.type = 'hidden';
input.name = name;
return input;
};
window.cbi_submit = function(elem, name, value, action) {
var form = elem.form || findParent(elem, 'form');
if (!form)
return false;
if (action)
form.action = action;
if (name) {
var hidden = form.querySelector('input[type="hidden"][name="%s"]'.format(name)) ||
makeHidden(name);
hidden.value = value || '1';
form.appendChild(hidden);
}
form.submit();
return true;
};
}
})();

View File

@ -0,0 +1,92 @@
module("luci.controller.tasks-lib", package.seeall)
function index()
entry({"admin", "system", "tasks", "status"}, call("tasks_status")).dependent=false
entry({"admin", "system", "tasks", "log"}, call("tasks_log")).dependent=false
entry({"admin", "system", "tasks", "stop"}, post("tasks_stop")).dependent=false
end
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local ltn12 = require "luci.ltn12"
local taskd = require "luci.model.tasks"
function tasks_status()
local data = taskd.status(luci.http.formvalue("task_id"))
luci.http.prepare_content("application/json")
luci.http.write_json(data)
end
function tasks_log()
local wait = 107
local task_id = luci.http.formvalue("task_id")
local offset = luci.http.formvalue("offset")
offset = offset and tonumber(offset) or 0
local logpath = "/var/log/tasks/"..task_id..".log"
local i
local logfd = io.open(logpath, "rb")
if logfd == nil then
luci.http.status(404)
luci.http.write("log not found")
return
end
local size = logfd:seek("end")
if size < offset then
luci.http.status(205, "Reset Content")
luci.http.write("reset offset")
return
end
i = 0
while (i < wait)
do
if size > offset then
break
end
nixio.nanosleep(0, 10000000) -- sleep 10ms
size = logfd:seek("end")
i = i+1
end
if i == wait then
logfd:close()
luci.http.status(204)
luci.http.prepare_content("application/octet-stream")
return
end
logfd:seek("set", offset)
local write_log = function()
local buffer = logfd:read(4096)
if buffer and #buffer > 0 then
return buffer
else
logfd:close()
return nil
end
end
luci.http.prepare_content("application/octet-stream")
if logfd then
ltn12.pump.all(write_log, luci.http.write)
end
end
function tasks_stop()
local sys = require("luci.sys")
local task_id = luci.http.formvalue("task_id") or ""
if task_id == "" then
luci.http.status(400)
luci.http.write("task_id is empty")
return
end
if sys.call("/etc/init.d/tasks task_del "..task_id.." >/dev/null 2>&1") ~= 0 then
nixio.nanosleep(2, 10000000)
end
luci.http.status(204)
end

View File

@ -0,0 +1,100 @@
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local taskd = {}
local function output(data)
local ret={}
ret.running=data.running
if not data.running then
ret.exit_code=data.exit_code
if nil == ret.exit_code then
if data["data"] and data["data"]["exit_code"] and data["data"]["exit_code"] ~= "" then
ret.exit_code=tonumber(data["data"]["exit_code"])
else
ret.exit_code=143
end
end
end
ret.command=data["command"] and data["command"][4] or '#'
if data["data"] then
ret.start=tonumber(data["data"]["start"])
if not data.running and data["data"]["stop"] then
ret.stop=tonumber(data["data"]["stop"])
end
end
return ret
end
taskd.status = function (task_id)
task_id = task_id or ""
local data = util.trim(util.exec("/etc/init.d/tasks task_status "..task_id.." 2>/dev/null")) or ""
if data ~= "" then
data = jsonc.parse(data)
else
if task_id == "" then
data = {}
else
data = {running=false, exit_code=404}
end
end
if task_id ~= "" then
return output(data)
end
local ary={}
for k, v in pairs(data) do
ary[k] = output(v)
end
return ary
end
taskd.docker_map = function(config, task_id, script_path, title, desc)
require("luci.cbi")
require("luci.http")
require("luci.sys")
local translate = require("luci.i18n").translate
local m
m = luci.cbi.Map(config, title, desc)
m.template = "tasks/docker"
-- hide default buttons
m.pageaction = false
-- we want hook 'on_after_apply' works, 'apply_on_parse' can be true (rollback) or false (no rollback),
-- but 'apply_on_parse' must be true for luci 17.01 and below
m.apply_on_parse = true
m.script_path = script_path
m.task_id = task_id
m.auto_show_task = true
m.on_before_apply = function(self)
if self.uci.rollback then
-- luci 18.06+ has 'rollback' function
-- rollback dialog will show because 'apply_on_parse' is true,
-- hide rollback dialog by hook 'apply' function
local apply = self.uci.apply
self.uci.apply = function(uci, rollback)
apply(uci, false)
end
end
end
m.on_after_apply = function(self)
local cmd
local action = luci.http.formvalue("cbi.apply") or "null"
if "upgrade" == action or "install" == action
or "start" == action or "stop" == action or "restart" == action or "rm" == action then
cmd = string.format("\"%s\" %s", script_path, action)
end
if cmd then
if luci.sys.call("/etc/init.d/tasks task_add " .. task_id .. " " .. luci.util.shellquote(cmd) .. " >/dev/null 2>&1") ~= 0 then
self.task_start_failed = true
self.message = translate("Config saved, but apply failed")
end
else
self.message = translate("Unknown command: ") .. action
end
if self.message then
self.auto_show_task = false
end
end
return m
end
return taskd

View File

@ -0,0 +1,56 @@
<% if self.task_start_failed then %>
<div class="alert-message warning"><%:Another task running, try again later.%> <a href="javascript:void(taskd.show_log('<%=self.task_id%>'))"><%:Click here to check running task%></a></div>
<% end %>
<%+cbi/map%>
<%
local task_running = false
local taskd = require "luci.model.tasks"
local status = taskd.status(self.task_id)
task_running = status.running
-%>
<div class="cbi-page-actions control-group">
<%
if not task_running then
%>
<%
local util = require "luci.util"
local container_status = util.trim(util.exec(self.script_path.." status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
if container_install then
-%>
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Upgrade%>/<%:Apply%>" onclick="cbi_submit(this, 'cbi.apply', 'upgrade')" />
<%
if container_running then
-%>
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Stop%>" onclick="cbi_submit(this, 'cbi.apply', 'stop')" />
<input class="btn cbi-button cbi-button-reload" type="button" value="<%:Restart%>" onclick="cbi_submit(this, 'cbi.apply', 'restart')" />
<% else %>
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Start%>" onclick="cbi_submit(this, 'cbi.apply', 'start')" />
<input class="btn cbi-button cbi-button-remove" type="button" value="<%:Remove%>" onclick="cbi_submit(this, 'cbi.apply', 'rm')" />
<% end
else %>
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Install%>" onclick="cbi_submit(this, 'cbi.apply', 'install')" />
<% end
else
%>
<input class="btn cbi-button cbi-button-apply" type="button" value="<%:Task Running%>&hellip;" onclick="taskd.show_log('<%=self.task_id%>')" />
<%
end
%>
</div>
<%+tasks/embed%>
<%
if self.auto_show_task and task_running then
-%>
<script>
taskd.show_log("<%=self.task_id%>");
</script>
<%
end
%>

View File

@ -0,0 +1,34 @@
<%+xterm/embed%>
<link rel="stylesheet" href="<%=resource%>/tasks/tasks.css<%# ?v=PKG_VERSION %>">
<script src="<%=resource%>/tasks/tasks.js<%# ?v=PKG_VERSION %>"></script>
<%
local i18n = {}
local function tr(str)
i18n[str]=translate(str)
end
tr("Stop running task?")
tr("Stopped at:")
tr("Finished at:")
tr("Failed at:")
tr("Lost login status")
tr("Fetch log failed, retrying...")
tr("Task does not exist or has been deleted")
-%>
<script>
window.taskd.csrfToken="<%=token%>";
window.taskd.i18n=<% luci.http.write_json(i18n) %>;
window.taskd.dialog_template=`
<div id="tasks_dialog">
<div class="dialog-title-bar">
<span class="dialog-title" id="tasks_id"></span>
<span class="dialog-icons">
<span class="dialog-icon dialog-icon-close" title="<%:Stop and Remove%>"></span>
<span class="dialog-icon dialog-icon-min" title="<%:Hide%>"></span>
</span>
</div>
<div class="dialog-content">
<div id="tasks_xterm_log"></div>
</div>
</div>
`;
</script>

View File

@ -0,0 +1,15 @@
clean:
compile:
include $(TOPDIR)/rules.mk
LUCI_NAME:=luci-lib-dummy
INCLUDE_DIR:=./dummy
include $(TOPDIR)/feeds/luci/luci.mk
install:
mkdir -p "$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n"
$(foreach lang,$(LUCI_LANGUAGES),$(foreach po,$(wildcard ${CURDIR}/po/$(lang)/*.po), \
po2lmo $(po) \
$(DESTDIR)$(LUCI_LIBRARYDIR)/i18n/$(basename $(notdir $(po))).$(lang).lmo;))

View File

@ -0,0 +1,2 @@
define BuildPackage
endef

View File

@ -0,0 +1,41 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Stop running task?"
msgstr "删除运行中的任务?"
msgid "Finished at:"
msgstr "完成于:"
msgid "Failed at:"
msgstr "失败于:"
msgid "Lost login status"
msgstr "丢失登陆状态"
msgid "Fetch log failed, retrying..."
msgstr "拉取日志失败,正在重试..."
msgid "Task does not exist or has been deleted"
msgstr "任务不存在或已删除"
msgid "Stop and Remove"
msgstr "停止并删除"
msgid "Hide"
msgstr "隐藏"
msgid "Config saved, but apply failed"
msgstr "配置已保存,但应用失败"
msgid "Unknown command: "
msgstr "未知命令:"
msgid "Another task running, try again later."
msgstr "已有后台任务运行中,请稍后重试。"
msgid "Click here to check running task"
msgstr "点此查看运行中的任务"
msgid "Task Running"
msgstr "任务执行中"

21
luci-lib-xterm/Makefile Normal file
View File

@ -0,0 +1,21 @@
#
# Copyright (c) 2017-2019, The xterm.js authors (MIT License)
# Copyright (c) 2014-2017, SourceLair, Private Company (www.sourcelair.com) (MIT License)
# Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
#
# This is free software, licensed under the MIT License.
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Xterm.js library
LUCI_DEPENDS:=
PKG_LICENSE:=MIT
PKG_VERSION:=4.18.0
PKG_RELEASE:=
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,180 @@
/**
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
* @license MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Originally forked from (with the author's permission):
* Fabrice Bellard's javascript vt100 for jslinux:
* http://bellard.org/jslinux/
* Copyright (c) 2011 Fabrice Bellard
* The original design remains. The terminal itself
* has been extended to include xterm CSI codes, among
* other features.
*/
/**
* Default styles for xterm.js
*/
.xterm {
position: relative;
user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
}
.xterm.focus,
.xterm:focus {
outline: none;
}
.xterm .xterm-helpers {
position: absolute;
top: 0;
/**
* The z-index of the helpers must be higher than the canvases in order for
* IMEs to appear on top.
*/
z-index: 5;
}
.xterm .xterm-helper-textarea {
padding: 0;
border: 0;
margin: 0;
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
position: absolute;
opacity: 0;
left: -9999em;
top: 0;
width: 0;
height: 0;
z-index: -5;
/** Prevent wrapping so the IME appears against the textarea at the correct position */
white-space: nowrap;
overflow: hidden;
resize: none;
}
.xterm .composition-view {
/* TODO: Composition position got messed up somewhere */
background: #000;
color: #FFF;
display: none;
position: absolute;
white-space: nowrap;
z-index: 1;
}
.xterm .composition-view.active {
display: block;
}
.xterm .xterm-viewport {
/* On OS X this is required in order for the scroll bar to appear fully opaque */
background-color: #000;
overflow-y: scroll;
cursor: default;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
}
.xterm .xterm-screen {
position: relative;
}
.xterm .xterm-screen canvas {
position: absolute;
left: 0;
top: 0;
}
.xterm .xterm-scroll-area {
visibility: hidden;
}
.xterm-char-measure-element {
display: inline-block;
visibility: hidden;
position: absolute;
top: 0;
left: -9999em;
line-height: normal;
}
.xterm {
cursor: text;
}
.xterm.enable-mouse-events {
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
cursor: default;
}
.xterm.xterm-cursor-pointer,
.xterm .xterm-cursor-pointer {
cursor: pointer;
}
.xterm.column-select.focus {
/* Column selection mode */
cursor: crosshair;
}
.xterm .xterm-accessibility,
.xterm .xterm-message {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 10;
color: transparent;
}
.xterm .live-region {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.xterm-dim {
opacity: 0.5;
}
.xterm-underline {
text-decoration: underline;
}
.xterm-strikethrough {
text-decoration: line-through;
}
.xterm-screen .xterm-decoration-container .xterm-decoration {
z-index: 6;
position: absolute;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
<link rel="stylesheet" href="<%=resource%>/xterm/xterm.css<%# ?v=PKG_VERSION %>">
<script src="<%=resource%>/xterm/xterm.js<%# ?v=PKG_VERSION %>"></script>

View File

@ -0,0 +1,9 @@
# Openwrt-actions
## 使用步骤
1. 选择actions标签选择Build IPKs![image](https://user-images.githubusercontent.com/1214708/153843131-615197e2-4ff4-4c0b-b30a-372e1c513158.png)
2. 点击run workflow输入要编译的插件名称空格隔开或者填“all”用来编译所有插件然后开始编译![image](https://user-images.githubusercontent.com/1214708/153843217-0591a7e6-4758-461e-8b2b-9bb830b87fb2.png)
3. 等待编译完成,点击任务进入详情页
4. 在详情页下载插件压缩包![image](https://user-images.githubusercontent.com/1214708/153843272-81843b45-6dc8-4945-871f-a9a467f63c33.png)

View File

@ -0,0 +1,18 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.0-20220830
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for heimdall
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+docker +luci-lib-taskd
define Package/luci-app-heimdall/conffiles
/etc/config/heimdall
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.heimdall", package.seeall)
function index()
entry({"admin", "services", "heimdall"}, alias("admin", "services", "heimdall", "config"), _("Heimdall"), 30).dependent = true
entry({"admin", "services", "heimdall", "config"}, cbi("heimdall"))
end

View File

@ -0,0 +1,35 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local m, s, o
m = taskd.docker_map("heimdall", "heimdall", "/usr/libexec/istorec/heimdall.sh",
translate("Heimdall"),
translate("Heimdall is an elegant solution to organise all your web applications.")
.. translate("Official website:") .. ' <a href=\"https://github.com/linuxserver/Heimdall\" target=\"_blank\">https://github.com/linuxserver/Heimdall</a>')
s = m:section(SimpleSection, translate("Service Status"), translate("Heimdall status:"))
s:append(Template("heimdall/status"))
s = m:section(TypedSection, "heimdall", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "http_port", translate("HTTP Port").."<b>*</b>")
o.rmempty = false
o.default = "8088"
o.datatype = "port"
o = s:option(Value, "https_port", translate("HTTPS Port").."<b>*</b>")
o.rmempty = false
o.default = "8089"
o.datatype = "port"
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.default = "/root/heimdall/config"
o.datatype = "string"
return m

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/heimdall.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:Heimdall is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:Heimdall is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/heimdall.sh port"))
if port == "" then
port="8088"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open Heimdall%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,44 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "Heimdall is an elegant solution to organise all your web applications."
msgstr "Heimdall 是组织所有 Web 应用程序的优雅解决方案。"
msgid "Config path"
msgstr "配置文件路径"
msgid "Port"
msgstr "端口"
msgid "HTTP Port"
msgstr "HTTP 端口"
msgid "HTTPS Port"
msgstr "HTTPS 端口"
msgid "Service Status"
msgstr "服务状态"
msgid "Heimdall status:"
msgstr "Heimdall 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "Heimdall is running"
msgstr "Heimdall 运行中"
msgid "Heimdall is not running"
msgstr "Heimdall 未运行"
msgid "Open Heimdall"
msgstr "打开 Heimdall"

View File

@ -0,0 +1,4 @@
config heimdall
option 'http_port' '8088'
option 'https_port' '8089'
option 'config_path' '/root/heimdall/config'

View File

@ -0,0 +1,84 @@
#!/bin/sh
ACTION=${1}
shift 1
get_image() {
IMAGE_NAME="lscr.io/linuxserver/heimdall:latest"
}
do_install() {
get_image
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f heimdall
do_install_detail
}
do_install_detail() {
local config=`uci get heimdall.@heimdall[0].config_path 2>/dev/null`
local http_port=`uci get heimdall.@heimdall[0].http_port 2>/dev/null`
local https_port=`uci get heimdall.@heimdall[0].https_port 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
[ -z "$http_port" ] && http_port=8088
[ -z "$https_port" ] && http_port=8089
local cmd="docker run --restart=unless-stopped -d \
-v \"$config:/config\" \
--dns=172.17.0.1 \
-p $http_port:80 \
-p $https_port:443 "
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
local tz="`cat /tmp/TZ`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
cmd="$cmd --name heimdall \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the heimdall"
echo " upgrade Upgrade the heimdall"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the heimdall"
echo " status Heimdall status"
echo " port Heimdall port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f heimdall
;;
"start" | "stop" | "restart")
docker ${ACTION} heimdall
;;
"status")
docker ps --all -f 'name=heimdall' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=heimdall' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,18 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.0-20220830
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for homeassistant
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+docker +luci-lib-taskd
define Package/luci-app-homeassistant/conffiles
/etc/config/homeassistant
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.homeassistant", package.seeall)
function index()
entry({"admin", "services", "homeassistant"}, alias("admin", "services", "homeassistant", "config"), _("Home Assistant"), 30).dependent = true
entry({"admin", "services", "homeassistant", "config"}, cbi("homeassistant"))
end

View File

@ -0,0 +1,25 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local m, s, o
m = taskd.docker_map("homeassistant", "homeassistant", "/usr/libexec/istorec/homeassistant.sh",
translate("Home Assistant"),
translate("Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts.")
.. translate("Official website:") .. ' <a href=\"https://www.home-assistant.io/\" target=\"_blank\">https://www.home-assistant.io/</a>')
s = m:section(SimpleSection, translate("Service Status"), translate("Home Assistant status:"))
s:append(Template("homeassistant/status"))
s = m:section(TypedSection, "homeassistant", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.default = "/root/homeassistant/config"
o.datatype = "string"
return m

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/homeassistant.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:Home Assistant is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:Home Assistant is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/homeassistant.sh port"))
if port == "" then
port="8123"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open the Home Assistant%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,35 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts."
msgstr "将本地控制和隐私放在首位的开源家庭自动化,由全世界 DIY 爱好者组成的社区驱动。"
msgid "Config path"
msgstr "配置文件路径"
msgid "Service Status"
msgstr "服务状态"
msgid "Home Assistant status:"
msgstr "Home Assistant 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "Home Assistant is running"
msgstr "Home Assistant 运行中"
msgid "Home Assistant is not running"
msgstr "Home Assistant 未运行"
msgid "Open the Home Assistant"
msgstr "打开 Home Assistant"

View File

@ -0,0 +1,2 @@
config homeassistant
option 'config_path' '/root/homeassistant/config'

View File

@ -0,0 +1,76 @@
#!/bin/sh
ACTION=${1}
shift 1
get_image() {
IMAGE_NAME="homeassistant/home-assistant:latest"
}
do_install() {
get_image
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f homeassistant
do_install_detail
}
do_install_detail() {
local config=`uci get homeassistant.@homeassistant[0].config_path 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
local cmd="docker run --restart=unless-stopped -d \
-v \"$config:/config\" \
--privileged \
--network=host \
--dns=127.0.0.1 "
local tz="`cat /tmp/TZ`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
cmd="$cmd --name homeassistant \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the homeassistant"
echo " upgrade Upgrade the homeassistant"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the homeassistant"
echo " status Home Assistant status"
echo " port Home Assistant port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f homeassistant
;;
"start" | "stop" | "restart")
docker ${ACTION} homeassistant
;;
"status")
docker ps --all -f 'name=homeassistant' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=homeassistant' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,19 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.0-20220718
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for jackett
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+docker +luci-lib-taskd
define Package/luci-app-jackett/conffiles
/etc/config/jackett
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.jackett", package.seeall)
function index()
entry({"admin", "services", "jackett"}, alias("admin", "services", "jackett", "config"), _("Jackett"), 30).dependent = true
entry({"admin", "services", "jackett", "config"}, cbi("jackett"))
end

View File

@ -0,0 +1,37 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local m, s, o
m = taskd.docker_map("jackett", "jackett", "/usr/libexec/istorec/jackett.sh",
translate("Jackett"),
translate("Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps.")
.. translate("Official website:") .. ' <a href=\"https://github.com/Jackett/Jackett\" target=\"_blank\">https://github.com/Jackett/Jackett</a>')
s = m:section(SimpleSection, translate("Service Status"), translate("Jackett status:"))
s:append(Template("jackett/status"))
s = m:section(TypedSection, "jackett", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "port", translate("Port").."<b>*</b>")
o.rmempty = false
o.default = "9117"
o.datatype = "port"
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o = s:option(Value, "save_path", translate("Torrent save path").."<b>*</b>", translate("Usually use the monitoring folder of the torrent download tool"))
o.rmempty = false
o.datatype = "string"
o = s:option(Flag, "auto_update", translate("Auto update"))
o.default = 1
o.rmempty = false
return m

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/jackett.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:Jackett is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:Jackett is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/jackett.sh port"))
if port == "" then
port="9117"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open Jackett%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,47 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps."
msgstr "Jackett 是维护索引器抓取和翻译逻辑的单一存储库 - 消除了其他应用程序的负担。"
msgid "Config path"
msgstr "配置文件路径"
msgid "Torrent save path"
msgstr "种子保存路径"
msgid "Port"
msgstr "端口"
msgid "Auto update"
msgstr "自动更新"
msgid "Service Status"
msgstr "服务状态"
msgid "Jackett status:"
msgstr "Jackett 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "Jackett is running"
msgstr "Jackett 运行中"
msgid "Jackett is not running"
msgstr "Jackett 未运行"
msgid "Open Jackett"
msgstr "打开 Jackett"
msgid "Usually use the monitoring folder of the torrent download tool"
msgstr "通常使用BT下载工具的监控文件夹"

View File

@ -0,0 +1,5 @@
config jackett
option 'auto_update' '1'
option 'port' '9117'
option 'save_path' ''
option 'config_path' '/root/jackett/config'

View File

@ -0,0 +1,93 @@
#!/bin/sh
ACTION=${1}
shift 1
get_image() {
IMAGE_NAME="linuxserver/jackett:latest"
}
do_install() {
get_image
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f jackett
do_install_detail
}
do_install_detail() {
local save_path=`uci get jackett.@jackett[0].save_path 2>/dev/null`
local config=`uci get jackett.@jackett[0].config_path 2>/dev/null`
local port=`uci get jackett.@jackett[0].port 2>/dev/null`
local auto_update=`uci get jackett.@jackett[0].auto_update 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
if [ -z "$save_path" ]; then
echo "save path is empty!"
exit 1
fi
[ -z "$port" ] && port=9117
local cmd="docker run --restart=unless-stopped -d \
-v \"$config:/config\" \
-v \"$save_path:/downloads\" \
--dns=172.17.0.1 \
-p $port:9117 "
local tz="`cat /tmp/TZ`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
if [ -n "$auto_update" ]; then
if [ "$auto_update" = 1 ]; then
cmd="$cmd -e AUTO_UPDATE=true"
else
cmd="$cmd -e AUTO_UPDATE=false"
fi
fi
cmd="$cmd --name jackett \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the jackett"
echo " upgrade Upgrade the jackett"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the jackett"
echo " status Jackett status"
echo " port Jackett port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f jackett
;;
"start" | "stop" | "restart")
docker ${ACTION} jackett
;;
"status")
docker ps --all -f 'name=jackett' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=jackett' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,19 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.5-20220729
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for jellyfin
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+docker +luci-lib-taskd
define Package/luci-app-jellyfin/conffiles
/etc/config/jellyfin
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.jellyfin", package.seeall)
function index()
entry({"admin", "services", "jellyfin"}, alias("admin", "services", "jellyfin", "config"), _("Jellyfin"), 30).dependent = true
entry({"admin", "services", "jellyfin", "config"}, cbi("jellyfin"))
end

View File

@ -0,0 +1,39 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local m, s, o
m = taskd.docker_map("jellyfin", "jellyfin", "/usr/share/jellyfin/install.sh",
translate("Jellyfin"),
translate("Jellyfin is the volunteer-built media solution that puts you in control of your media. Stream to any device from your own server, with no strings attached. Your media, your server, your way.")
.. translate("Official website:") .. ' <a href=\"https://jellyfin.org/\" target=\"_blank\">https://jellyfin.org/</a>')
s = m:section(SimpleSection, translate("Service Status"), translate("Jellyfin status:"))
s:append(Template("jellyfin/status"))
s = m:section(TypedSection, "jellyfin", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Flag, "hostnet", translate("Host network"), translate("Jellyfin running in host network, for DLNA application, port is always 8096 if enabled"))
o.default = 0
o.rmempty = false
o = s:option(Value, "port", translate("Port").."<b>*</b>")
o.default = "8096"
o.datatype = "port"
o:depends("hostnet", 0)
o = s:option(Value, "media_path", translate("Media path"))
o.datatype = "string"
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o = s:option(Value, "cache_path", translate("Transcode cache path"), translate("Default use 'transcodes' in 'config path' if not set, please make sure there has enough space"))
o.datatype = "string"
return m

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/share/jellyfin/install.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:Jellyfin is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:Jellyfin is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/share/jellyfin/install.sh port"))
if port == "" then
port="8096"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open Jellyfin%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,53 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "Jellyfin is the volunteer-built media solution that puts you in control of your media. Stream to any device from your own server, with no strings attached. Your media, your server, your way."
msgstr "Jellyfin 是志愿者构建的媒体解决方案,可让您控制自己的电影等媒体,并没带任何条件的让您从各种设备去观看您的媒体。"
msgid "Media path"
msgstr "媒体路径"
msgid "Config path"
msgstr "配置文件路径"
msgid "Transcode cache path"
msgstr "转码缓存路径"
msgid "Port"
msgstr "端口"
msgid "Host network"
msgstr "宿主网络"
msgid "Jellyfin running in host network, for DLNA application, port is always 8096 if enabled"
msgstr "在宿主网络运行 Jellyfin以支持 DLNA 等应用例如投屏如果启用则端口固定为8096"
msgid "Default use 'transcodes' in 'config path' if not set, please make sure there has enough space"
msgstr "留空则使用配置文件路径下的 transcodes请确保有足够空间"
msgid "Service Status"
msgstr "服务状态"
msgid "Jellyfin status:"
msgstr "Jellyfin 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "Jellyfin is running"
msgstr "Jellyfin 运行中"
msgid "Jellyfin is not running"
msgstr "Jellyfin 未运行"
msgid "Open Jellyfin"
msgstr "打开 Jellyfin"

View File

@ -0,0 +1,7 @@
config jellyfin
option 'hostnet' '0'
option 'port' '8096'
option 'image' 'default'
option 'media_path' ''
option 'config_path' '/root/jellyfin/config'
option 'cache_path' ''

View File

@ -0,0 +1,11 @@
#!/bin/sh
image_name=`uci get jellyfin.@jellyfin[0].image 2>/dev/null`
if [ "$image_name" == "jjm2473/jellyfin-rtk:latest" ]; then
uci -q batch <<-EOF >/dev/null
set jellyfin.@jellyfin[0].image="default"
commit jellyfin
EOF
fi
exit 0

View File

@ -0,0 +1,137 @@
#!/bin/sh
# Author Xiaobao(xiaobao@linkease.com)
ACTION=${1}
shift 1
ARCH="default"
IMAGE_NAME='default'
get_image() {
if grep -Eq ',rtd-?129.$' /proc/device-tree/compatible 2>/dev/null; then
ARCH="rtd129x"
fi
IMAGE_NAME=`uci get jellyfin.@jellyfin[0].image 2>/dev/null`
if [ -z "$IMAGE_NAME" -o "$IMAGE_NAME" == "default" ]; then
if [ "${ARCH}" = "rtd129x" ]; then
IMAGE_NAME="jjm2473/jellyfin-rtk:latest"
if uname -r | grep -q '^4\.9\.'; then
IMAGE_NAME="jjm2473/jellyfin-rtk:4.9-latest"
fi
else
IMAGE_NAME="jellyfin/jellyfin"
fi
fi
}
do_install() {
get_image
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f jellyfin
do_install_detail
}
do_install_detail() {
local hostnet=`uci get jellyfin.@jellyfin[0].hostnet 2>/dev/null`
local media=`uci get jellyfin.@jellyfin[0].media_path 2>/dev/null`
local config=`uci get jellyfin.@jellyfin[0].config_path 2>/dev/null`
local cache=`uci get jellyfin.@jellyfin[0].cache_path 2>/dev/null`
local port=`uci get jellyfin.@jellyfin[0].port 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
[ -z "$port" ] && port=8096
local cmd="docker run --restart=unless-stopped -d -v \"$config:/config\" "
if [ "${ARCH}" = "rtd129x" ]; then
cmd="$cmd\
--device /dev/rpc0:/dev/rpc0 \
--device /dev/rpc1:/dev/rpc1 \
--device /dev/rpc2:/dev/rpc2 \
--device /dev/rpc3:/dev/rpc3 \
--device /dev/rpc4:/dev/rpc4 \
--device /dev/rpc5:/dev/rpc5 \
--device /dev/rpc6:/dev/rpc6 \
--device /dev/rpc7:/dev/rpc7 \
--device /dev/rpc100:/dev/rpc100 \
--device /dev/uio250:/dev/uio250 \
--device /dev/uio251:/dev/uio251 \
--device /dev/uio252:/dev/uio252 \
--device /dev/uio253:/dev/uio253 \
--device /dev/ion:/dev/ion \
--device /dev/ve3:/dev/ve3 \
--device /dev/vpu:/dev/vpu \
--device /dev/memalloc:/dev/memalloc \
-v /tmp/shm:/dev/shm \
-v /sys/class/uio:/sys/class/uio \
-v /var/tmp/vowb:/var/tmp/vowb \
--pid=host "
elif [ -d /dev/dri ]; then
cmd="$cmd\
--device /dev/dri:/dev/dri \
--privileged "
fi
if [ "$hostnet" = 1 ]; then
cmd="$cmd\
--dns=127.0.0.1 \
--network=host "
else
cmd="$cmd\
--dns=172.17.0.1 \
-p $port:8096 "
fi
local tz="`cat /tmp/TZ`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
[ -z "$cache" ] || cmd="$cmd -v \"$cache:/config/transcodes\""
[ -z "$media" ] || cmd="$cmd -v \"$media:/media\""
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
cmd="$cmd --name jellyfin \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the jellyfin"
echo " upgrade Upgrade the jellyfin"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the jellyfin"
echo " status Jellyfin status"
echo " port Jellyfin port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f jellyfin
;;
"start" | "stop" | "restart")
docker ${ACTION} jellyfin
;;
"status")
docker ps --all -f 'name=jellyfin' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=jellyfin' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,18 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.2.0-20220830
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for kodexplorer
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+docker +luci-lib-taskd
define Package/luci-app-kodexplorer/conffiles
/etc/config/kodexplorer
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.kodexplorer", package.seeall)
function index()
entry({"admin", "services", "kodexplorer"}, alias("admin", "services", "kodexplorer", "config"), _("KodExplorer"), 30).dependent = true
entry({"admin", "services", "kodexplorer", "config"}, cbi("kodexplorer"))
end

View File

@ -0,0 +1,30 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local m, s, o
m = taskd.docker_map("kodexplorer", "kodexplorer", "/usr/libexec/istorec/kodexplorer.sh",
translate("KodExplorer"),
translate("Private cloud online document management solution based on web technology.")
.. translate("Official website:") .. ' <a href=\"https://kodcloud.com/\" target=\"_blank\">https://kodcloud.com/</a>')
s = m:section(SimpleSection, translate("Service Status"), translate("KodExplorer status:"))
s:append(Template("kodexplorer/status"))
s = m:section(TypedSection, "kodexplorer", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "port", translate("Port").."<b>*</b>")
o.rmempty = false
o.default = "8081"
o.datatype = "port"
o = s:option(Value, "cache_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.default = "/mnt/sda1/kodexplorer"
o.datatype = "string"
return m

View File

@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/kodexplorer.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:KodExplorer is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:KodExplorer is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/kodexplorer.sh port"))
if port == "" then
port="8081"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open KodExplorer%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,41 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "KodExplorer"
msgstr "可道云"
msgid "Official website:"
msgstr "官方网站:"
msgid "Private cloud online document management solution based on web technology."
msgstr "基于Web技术的私有云在线文档管理解决方案。"
msgid "Config path"
msgstr "配置文件路径"
msgid "Port"
msgstr "端口"
msgid "Service Status"
msgstr "服务状态"
msgid "KodExplorer status:"
msgstr "可道云的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "KodExplorer is running"
msgstr "可道云运行中"
msgid "KodExplorer is not running"
msgstr "可道云未运行"
msgid "Open KodExplorer"
msgstr "打开可道云"

View File

@ -0,0 +1,3 @@
config kodexplorer
option 'cache_path' '/mnt/sda1/kodexplorer'
option 'port' '8081'

View File

@ -0,0 +1,81 @@
#!/bin/sh
ACTION=${1}
shift 1
get_image() {
IMAGE_NAME="kodcloud/kodbox:latest"
}
do_install() {
get_image
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f kodexplorer
do_install_detail
}
do_install_detail() {
local config=`uci get kodexplorer.@kodexplorer[0].cache_path 2>/dev/null`
local port=`uci get kodexplorer.@kodexplorer[0].port 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
[ -z "$port" ] && port=8081
local cmd="docker run --restart=unless-stopped -d \
-v \"$config:/var/www/html\" \
--dns=172.17.0.1 \
-p $port:80 "
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
local tz="`cat /tmp/TZ`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
cmd="$cmd --name kodexplorer \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the kodexplorer"
echo " upgrade Upgrade the kodexplorer"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the kodexplorer"
echo " status KodExplorer status"
echo " port KodExplorer port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f kodexplorer
;;
"start" | "stop" | "restart")
docker ${ACTION} kodexplorer
;;
"status")
docker ps --all -f 'name=kodexplorer' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=kodexplorer' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,18 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.1.0-20220903
PKG_RELEASE:=
LUCI_TITLE:=LuCI support for nastools
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+docker +luci-lib-taskd
define Package/luci-app-nastools/conffiles
/etc/config/nastools
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,7 @@
module("luci.controller.nastools", package.seeall)
function index()
entry({"admin", "services", "nastools"}, alias("admin", "services", "nastools", "config"), _("NasTools"), 30).dependent = true
entry({"admin", "services", "nastools", "config"}, cbi("nastools"))
end

View File

@ -0,0 +1,33 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local m, s, o
m = taskd.docker_map("nastools", "nastools", "/usr/libexec/istorec/nastools.sh",
translate("NasTools"),
translate("NasTools is a tools for resource aggregation running in NAS.")
.. translate("Official website:") .. ' <a href=\"https://github.com/jxxghp/nas-tools\" target=\"_blank\">https://github.com/jxxghp/nas-tools</a>')
s = m:section(SimpleSection, translate("Service Status"), translate("NasTools status:"))
s:append(Template("nastools/status"))
s = m:section(TypedSection, "nastools", translate("Setup"), translate("The following parameters will only take effect during installation or upgrade:"))
s.addremove=false
s.anonymous=true
o = s:option(Value, "http_port", translate("Port").."<b>*</b>")
o.rmempty = false
o.default = "3003"
o.datatype = "port"
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o = s:option(Flag, "auto_upgrade", translate("Auto update"))
o.default = 1
o.rmempty = false
return m

View File

@ -0,0 +1,32 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/nastools.sh status"))
local container_install = (string.len(container_status) > 0)
local container_running = container_status == "running"
-%>
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field">
<% if container_running then %>
<button class="cbi-button cbi-button-success" disabled="true"><%:NasTools is running%></button>
<div class="cbi-value-description"><%:Default username: admin, password: password%></div>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:NasTools is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/nastools.sh port"))
if port == "" then
port="3003"
end
-%>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title">&nbsp;</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" name="start" value="<%:Open NasTools%>" onclick="window.open('http://'+location.hostname+':<%=port%>/', '_blank')">
</div>
</div>
<% end %>

View File

@ -0,0 +1,44 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "NasTools is a tools for resource aggregation running in NAS."
msgstr "NasTools 是汇聚了电影搜索,下载,订阅,观看等等 NAS 功能的工具集合。"
msgid "Config path"
msgstr "配置文件路径"
msgid "Port"
msgstr "端口"
msgid "Auto update"
msgstr "自动更新"
msgid "Service Status"
msgstr "服务状态"
msgid "NasTools status:"
msgstr "NasTools 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "NasTools is running"
msgstr "NasTools 运行中"
msgid "Default username: admin, password: password"
msgstr "默认用户名admin密码password"
msgid "NasTools is not running"
msgstr "NasTools 未运行"
msgid "Open NasTools"
msgstr "打开 NasTools"

View File

@ -0,0 +1,4 @@
config nastools
option 'config_path' '/root/nastools/config'
option 'http_port' '3003'
option 'auto_upgrade' '0'

View File

@ -0,0 +1,89 @@
#!/bin/sh
ACTION=${1}
shift 1
get_image() {
IMAGE_NAME="jxxghp/nas-tools"
}
do_install() {
get_image
echo "docker pull ${IMAGE_NAME}"
docker pull ${IMAGE_NAME}
docker rm -f nastools
do_install_detail
}
do_install_detail() {
local config=`uci get nastools.@nastools[0].config_path 2>/dev/null`
local port=`uci get nastools.@nastools[0].http_port 2>/dev/null`
local auto_update=`uci get nastools.@nastools[0].auto_upgrade 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
[ -z "$port" ] && port=3003
local cmd="docker run --restart=unless-stopped -d \
--hostname nastools \
-v \"$config:/config\" \
--dns=172.17.0.1 \
-p $port:3000 \
-e UMASK=000"
local tz="`cat /tmp/TZ`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
if [ -n "$auto_update" ]; then
if [ "$auto_update" = 1 ]; then
cmd="$cmd -e NASTOOL_AUTO_UPDATE=true"
else
cmd="$cmd -e NASTOOL_AUTO_UPDATE=false"
fi
fi
cmd="$cmd --name nastools \"$IMAGE_NAME\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the nastools"
echo " upgrade Upgrade the nastools"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the nastools"
echo " status NasTools status"
echo " port NasTools port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f nastools
;;
"start" | "stop" | "restart")
docker ${ACTION} nastools
;;
"status")
docker ps --all -f 'name=nastools' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=nastools' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*' | sed 's/0.0.0.0://'
;;
*)
usage
exit 1
;;
esac

View File

@ -0,0 +1,22 @@
# Copyright (C) 2016 Openwrt.org
# Copyright (C) 2020-2021 sirpdboy <herboy2008@gmail.com>
# https://github.com/sirpdboy/luci-app-netdata for v 1.30.1 cn
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for Netdata
LUCI_DEPENDS:=+netdata
LUCI_PKGARCH:=all
PKG_VERSION:=1.0
PKG_RELEASE:=20210610
define Build/Compile
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,30 @@
luci-app-netdata for OpenWRT/Lede
Install to OpenWRT/LEDE
git clone https://github.com/sirpdboy/luci-app-netdata
cp -r luci-app-netdata LEDE_DIR/package/luci-app-netdata
cd LEDE_DIR
./scripts/feeds update -a
./scripts/feeds install -a
make menuconfig
LuCI --->
1. Collections --->
<*> luci
3. Applications --->
<*> luci-app-netdata.........................LuCI support for Netdata
make package/new/luci-app-netdata/compile V=s

View File

@ -0,0 +1,12 @@
module("luci.controller.netdata", package.seeall)
function index()
if not (luci.sys.call("pidof netdata > /dev/null") == 0) then
return
end
local fs = require "nixio.fs"
entry({"admin","status","netdata"},template("netdata"),_("NetData"),10).leaf=true
end

View File

@ -0,0 +1,25 @@
-- Copyright 2018 Nick Peng (pymumu@gmail.com)
function index()
o = Map("netdate", "<font color='green'>" .. translate("实时监控") .."</font>", "<font color='purple'>" .. translate( "强大的实时监控数据,需要中文版请点击:【升级中文版】") .."</font>")
t = o:section(TypedSection, "netdate")
t.anonymous = true
t.description = translate(string.format("%s<br /><br />", status))
t:tab("base",translate("Basic Settings"))
e = t:taboption("base", Button, "restart", translate("手动更新"))
e.inputtitle = translate("升级中文版")
e.inputstyle = "reload"
e.write = function()
luci.sys.call("/usr/share/netdata/netdatacn 2>&1 >/dev/null")
luci.http.redirect(luci.dispatcher.build_url("admin","status","netdata"))
end
t=o:section(TypedSection,"rss_rules",translate("技术支持"))
t.anonymous = true
t:append(Template("feedback"))
return o

Some files were not shown because too many files have changed in this diff Show More