🌴 Sync 2026-03-05 23:51:42

This commit is contained in:
github-actions[bot] committed 2026-03-05 23:51:42 +08:00
1 parent 97c049ed0a
commit 0acff03804
14253 files changed
+3893239

No files matched your search

+18
View File
@@ -0,0 +1,18 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.2-20240822
PKG_RELEASE:=1
LUCI_TITLE:=LuCI support for Plex
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+lsblk +docker +dockerd +luci-lib-taskd +luci-lib-docker
define Package/luci-app-plex/conffiles
/etc/config/plex
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
+7
View File
@@ -0,0 +1,7 @@
module("luci.controller.plex", package.seeall)
function index()
entry({"admin", "services", "plex"}, alias("admin", "services", "plex", "config"), _("Plex"), 30).dependent = true
entry({"admin", "services", "plex", "config"}, cbi("plex"))
end
+82
View File
@@ -0,0 +1,82 @@
--[[
LuCI - Lua Configuration Interface
]]--
local taskd = require "luci.model.tasks"
local docker = require "luci.docker"
local plex_model = require "luci.model.plex"
local m, s, o
m = taskd.docker_map("plex", "plex", "/usr/libexec/istorec/plex.sh",
translate("Plex"),
translate("Plex is an streaming media service and a client–server media player platform, made by Plex, Inc.")
.. translate("Official website:") .. ' <a href=\"https://www.plex.tv/\" target=\"_blank\">https://www.plex.tv/</a>')
local dk = docker.new({socket_path="/var/run/docker.sock"})
local dockerd_running = dk:_ping().code == 200
local docker_info = dockerd_running and dk:info().body or {}
local docker_aspace = 0
if docker_info.DockerRootDir then
local statvfs = nixio.fs.statvfs(docker_info.DockerRootDir)
docker_aspace = statvfs and (statvfs.bavail * statvfs.bsize) or 0
end
s = m:section(SimpleSection, translate("Service Status"), translate("Plex status:"))
s:append(Template("plex/status"))
s = m:section(TypedSection, "main", translate("Setup"),
(docker_aspace < 2147483648 and
(translate("The free space of Docker is less than 2GB, which may cause the installation to fail.")
.. "<br>") or "") .. 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("Plex running in host network, for DLNA application. Port is always 32400 if enabled"))
o.default = 0
o.rmempty = false
o = s:option(Value, "claim_token", translate("Plex Claim Token"), translatef("Obtain token from %s", "<a href=\"https://plex.tv/claim\" target=\"_blank\">Plex</a>"))
o.datatype = "string"
o = s:option(Value, "port", translate("Port").."<b>*</b>")
o.default = "32400"
o.datatype = "port"
o:depends("hostnet", 0)
o = s:option(Value, "image_name", translate("Image").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
o.default = "linuxserver/plex:latest"
if "x86_64" == docker_info.Architecture then
o:value("plexinc/pms-docker:latest", "plexinc/pms-docker:latest [x86_64]")
o:value("plexinc/pms-docker:1.29.2.6364-6d72b0cf6", "plexinc/pms-docker:1.29.2.6364-6d72b0cf6 [x86_64]")
end
o:value("linuxserver/plex:latest", "linuxserver/plex:latest")
o:value("linuxserver/plex:1.29.2", "linuxserver/plex:1.29.2")
local blocks = plex_model.blocks()
local home = plex_model.home()
o = s:option(Value, "config_path", translate("Config path").."<b>*</b>")
o.rmempty = false
o.datatype = "string"
local paths, default_path = plex_model.find_paths(blocks, home, "Configs")
for _, val in pairs(paths) do
o:value(val, val)
end
o.default = default_path
o = s:option(Value, "media_path", translate("Media path"), translatef("Not required, all disk will be mounted under %s", "<a href='/cgi-bin/luci/admin/services/linkease/file/?path=/root/mnt' target='_blank'>/mnt</a>"))
o.datatype = "string"
o = s:option(Value, "cache_path", translate("Transcode cache path").."<b>*</b>", translate("Please make sure there has enough space"))
o.rmempty = false
o.datatype = "string"
local paths, default_path = plex_model.find_paths(blocks, home, "Caches")
for _, val in pairs(paths) do
o:value(val, val)
end
o.default = default_path
return m
+55
View File
@@ -0,0 +1,55 @@
local util = require "luci.util"
local jsonc = require "luci.jsonc"
local plex = {}
plex.blocks = function()
local f = io.popen("lsblk -s -f -b -o NAME,FSSIZE,MOUNTPOINT --json", "r")
local vals = {}
if f then
local ret = f:read("*all")
f:close()
local obj = jsonc.parse(ret)
for _, val in pairs(obj["blockdevices"]) do
local fsize = val["fssize"]
if fsize ~= nil and string.len(fsize) > 10 and val["mountpoint"] then
-- fsize > 1G
vals[#vals+1] = val["mountpoint"]
end
end
end
return vals
end
plex.home = function()
local uci = require "luci.model.uci".cursor()
local home_dirs = {}
home_dirs["main_dir"] = uci:get_first("quickstart", "main", "main_dir", "/root")
home_dirs["Configs"] = uci:get_first("quickstart", "main", "conf_dir", home_dirs["main_dir"].."/Configs")
home_dirs["Public"] = uci:get_first("quickstart", "main", "pub_dir", home_dirs["main_dir"].."/Public")
home_dirs["Downloads"] = uci:get_first("quickstart", "main", "dl_dir", home_dirs["Public"].."/Downloads")
home_dirs["Caches"] = uci:get_first("quickstart", "main", "tmp_dir", home_dirs["main_dir"].."/Caches")
return home_dirs
end
plex.find_paths = function(blocks, home_dirs, path_name)
local default_path = ''
local configs = {}
default_path = home_dirs[path_name] .. "/Plex"
if #blocks == 0 then
table.insert(configs, default_path)
else
for _, val in pairs(blocks) do
table.insert(configs, val .. "/" .. path_name .. "/Plex")
end
local without_conf_dir = "/root/" .. path_name .. "/Plex"
if default_path == without_conf_dir then
default_path = configs[1]
end
end
return configs, default_path
end
return plex
+31
View File
@@ -0,0 +1,31 @@
<%
local util = require "luci.util"
local container_status = util.trim(util.exec("/usr/libexec/istorec/plex.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"><%:Plex is running%></button>
<% else %>
<button class="cbi-button cbi-button-negative" disabled="true"><%:Plex is not running%></button>
<% end %>
</div>
</div>
<%
if container_running then
local port=util.trim(util.exec("/usr/libexec/istorec/plex.sh port"))
if port == "" then
port="32400"
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 Plex%>" onclick="window.open('http://'+location.hostname+':<%=port%>/web/', '_blank')">
</div>
</div>
<% end %>
+56
View File
@@ -0,0 +1,56 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Official website:"
msgstr "官方网站:"
msgid "Plex is an streaming media service and a client–server media player platform, made by Plex, Inc."
msgstr "Plex 是一个多媒体串流平台。"
msgid "Config path"
msgstr "配置文件路径"
msgid "Port"
msgstr "端口"
msgid "Service Status"
msgstr "服务状态"
msgid "Plex status:"
msgstr "Plex 的状态信息如下:"
msgid "Setup"
msgstr "安装配置"
msgid "The following parameters will only take effect during installation or upgrade:"
msgstr "以下参数只在安装或者升级时才会生效:"
msgid "Status"
msgstr "状态"
msgid "Plex is running"
msgstr "Plex 运行中"
msgid "Plex is not running"
msgstr "Plex 未运行"
msgid "Open Plex"
msgstr "打开 Plex"
msgid "Not required, all disk will be mounted under %s"
msgstr "可不填,所有硬盘都会挂载到 %s 下"
msgid "Plex running in host network, for DLNA application. Port is always 32400 if enabled"
msgstr "在宿主网络运行 Plex,以支持 DLNA 等应用,例如投屏,如果启用则端口固定为32400"
msgid "The free space of Docker is less than 2GB, which may cause the installation to fail."
msgstr "Docker 可用空间已不足2GB,可能导致安装失败。"
msgid "Plex Claim Token"
msgstr "Plex Claim 令牌"
msgid "Obtain token from %s"
msgstr "从 %s 获取令牌"
msgid "Please make sure there has enough space"
msgstr "请确保有足够空间"
+1
View File
@@ -0,0 +1 @@
zh-cn
+6
View File
@@ -0,0 +1,6 @@
config main
option 'hostnet' '0'
option 'claim_token' ''
option 'port' '32400'
option 'config_path' ''
@@ -0,0 +1,11 @@
#!/bin/sh
image_name=`uci get plex.@main[0].image_name 2>/dev/null`
if [ "$image_name" == "plexinc/pms-docker:latest" -a "`uname -m`" != "x86_64" ]; then
uci -q batch <<-EOF >/dev/null
set plex.@main[0].image_name=""
commit plex
EOF
fi
exit 0
+107
View File
@@ -0,0 +1,107 @@
#!/bin/sh
# Author Xiaobao(xiaobao@linkease.com)
ACTION=${1}
shift 1
do_install() {
local hostnet=`uci get plex.@main[0].hostnet 2>/dev/null`
local claim_token==`uci get plex.@main[0].claim_token 2>/dev/null`
local port=`uci get plex.@main[0].port 2>/dev/null`
local image_name=`uci get plex.@main[0].image_name 2>/dev/null`
local config=`uci get plex.@main[0].config_path 2>/dev/null`
local media=`uci get plex.@main[0].media_path 2>/dev/null`
local cache=`uci get plex.@main[0].cache_path 2>/dev/null`
if [ -z "$config" ]; then
echo "config path is empty!"
exit 1
fi
if [ -z "$cache" ]; then
echo "cache path is empty!"
exit 1
fi
[ -z "$image_name" ] && image_name="linuxserver/plex:latest"
echo "docker pull ${image_name}"
docker pull ${image_name}
docker rm -f plex
[ -z "$port" ] && port=32400
local cmd="docker run --restart=unless-stopped -d -h PlexServer -v \"$config:/config\" "
if [ -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 3005:3005/tcp \
-p 8324:8324/tcp \
-p 32469:32469/tcp \
-p 32410:32410/udp \
-p 32412:32412/udp \
-p 32413:32413/udp \
-p 32414:32414/udp \
-p $port:32400 "
fi
local tz="`uci get system.@system[0].zonename | sed 's/ /_/g'`"
[ -z "$tz" ] || cmd="$cmd -e TZ=$tz"
[ -z "$claim_token" ] || cmd="$cmd -e \"PLEX_CLAIM=$claim_token\""
cmd="$cmd -v \"$cache:/transcode\""
cmd="$cmd -v \"$cache:/config/Library/Application Support/Plex Media Server/Cache\""
[ -z "$media" ] || cmd="$cmd -v \"$media:/data\""
cmd="$cmd -v /mnt:/mnt"
mountpoint -q /mnt && cmd="$cmd:rslave"
cmd="$cmd --name plex \"$image_name\""
echo "$cmd"
eval "$cmd"
}
usage() {
echo "usage: $0 sub-command"
echo "where sub-command is one of:"
echo " install Install the plex"
echo " upgrade Upgrade the plex"
echo " rm/start/stop/restart Remove/Start/Stop/Restart the plex"
echo " status Plex status"
echo " port Plex port"
}
case ${ACTION} in
"install")
do_install
;;
"upgrade")
do_install
;;
"rm")
docker rm -f plex
;;
"start" | "stop" | "restart")
docker ${ACTION} plex
;;
"status")
docker ps --all -f 'name=^/plex$' --format '{{.State}}'
;;
"port")
docker ps --all -f 'name=^/plex$' --format '{{.Ports}}' | grep -om1 '0.0.0.0:[0-9]*->32400/tcp' | sed 's/0.0.0.0:\([0-9]*\)->.*/\1/'
;;
*)
usage
exit 1
;;
esac
@@ -0,0 +1,11 @@
{
"luci-app-plex": {
"description": "Grant UCI access for luci-app-plex",
"read": {
"uci": [ "plex" ]
},
"write": {
"uci": [ "plex" ]
}
}
}